当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_title
或
the_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_start
和loop_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
在这种情况下,语法可能更可取。