Get_Posts()是否比循环更有效?

时间:2013-11-27 作者:hrsetyono

在里面category.php, 我想获得该类别的帖子列表。

我找到了两种方法:使用get_posts($args)The Loop.

get_posts() 方法

$args = array (
  "category" => ID );
$posts = get_posts($args);
// then use foreach to loop the $posts
The Loop 方法

<?php if (have_posts() ): ?>
  <?php while (have_posts() ): the_post(); ?>
    ...
  <?php endwhile; ?>
<?php endif; ?>

So which one more efficient?

根据我的搜索,get_posts() 用于自定义模板,而The Loop 在遵循Wordpress命名约定的模板内使用。

我更喜欢get_posts() 但是如果与循环相比有很大的开销,我应该重新考虑一下。

1 个回复
最合适的回答,由SO网友:gmazzap 整理而成

当WordPress包含category.php (就像任何其他模板一样)主查询(即url触发的查询)是already ran:这意味着已经触发了对数据库的查询,这就是为什么在模板中可以运行循环而不调用查询的原因。

如果你打电话get_posts 您对数据库运行了另一个查询,即completely unnecessary once与WordPress已经运行的相同。

还要注意的是get_posts 只是一个包装WP_Query 因此,使用循环和foreach 语法,并不考虑查询本身,而是考虑使用查询结果的方式。

如果你愿意foreach 结束while (循环只是一个while 循环)您也可以使用它直接调用WP_Query:

$q = new WP_Query( $args ); // or $q = get_posts( $args );

foreach ( $q->posts as $post ) {
  // here your code e.g.
  $title = $post->title;
  $content = $post->content;
}
那么,为什么人们通常使用循环而不是这种循环呢?出于2个原因,至少:

设置全局$post 对象当你打电话的时候the_post() 在循环内部,该函数将变量全球化$post 包含当前post对象。许多核心功能和插件都依赖于该变量,因此设置往往很重要。但是,也可以使用foreach循环设置它,使用setup_postdata 函数,前面的代码变为:

global $post;
foreach ( $q->posts as $post ) {
  setup_postdata($post);
  // here your code e.g.
  $title = $post->title;
  $content = $post->content;
}
第二个原因是关于模板标记,而不是直接访问post对象属性:调用the_titlethe_content (或其他模板标记)过滤器在输出属性之前被激发,如果您不调用它们,输出可能不是您期望的输出,同样可以在我们的foreach循环中手动完成:

$q = new WP_Query( $args );
global $post;
foreach ( $q->posts as $post ) {
  setup_postdata($post);
  // here your code e.g.
  $title = apply_filters(\'the_title\', $post->title);
  $content = apply_filters(\'the_content\', $post->content);
}
最后一个代码块,可以认为与循环几乎相同。

我说几乎是因为还有另一件事不同:两个动作挂钩,loop_startloop_end, 由循环触发。一些插件可以使用它们,因此为了更好的兼容性,您应该执行以下操作:

$q = new WP_Query( $args );

global $post;
do_action_ref_array(\'loop_start\', array(&$q));
foreach ( $q->posts as $post ) {
  setup_postdata($post);
  // here your code e.g.
  $title = apply_filters(\'the_title\', $post->title);
  $content = apply_filters(\'the_content\', $post->content);
}
do_action_ref_array(\'loop_end\', array(&$q));
如前所述,这更好地用于自定义循环,但对于主查询,调用另一个WP_Query 不利于性能,不必要。然而,main查询只是一个WP_Query 实例,保存在全局变量中$wp_query, 因此,如果在模板中执行以下操作:

global $wp_query, $post;
do_action_ref_array(\'loop_start\', array(&$wp_query));
foreach ( $wp_query->posts as $post ) {
  setup_postdata($post);
  // here your code e.g.
  $title = apply_filters(\'the_title\', $post->title);
  $content = apply_filters(\'the_content\', $post->content);
}
do_action_ref_array(\'loop_end\', array(&$wp_query));
你正在做一些与循环非常相似(实际上完全相同)的事情,只是更加冗长,但如果你只是讨厌while 循环。。。

总之,对于主查询,出于兼容性原因,建议(但不是强制性的)使用循环:如果您不触发anction和filter挂钩,那么如果您安装任何插件,其中一些插件将无法工作。。。

但对于自定义循环,有时您不需要(或不希望)触发操作和筛选挂钩foreach 在这种情况下,语法可能更可取。

结束

相关推荐

Add filter to comments loop?

我正在制作一个插件,用于存储推荐人数据以供评论。我已经创建了数据库表,并且在进行注释时正确存储了数据。现在,我想为每个注释在注释块上附加一个自定义div。如何向注释循环添加过滤器?我想说“如果这个评论ID在我的表中有一个推荐人,那么在我的特殊div中打印出推荐人”。我可以自己写函数,我只需要在哪里注入函数的帮助。