wordpress中的2个查询方法query_posts()
和WP_Query
到底有什么区别和联系?分别应该在什么情形下使用?
各种博客教程中2种方法都有涉及,但是没有明确区分,让人比较困惑,这个问题怎么破?
主流的理解思路
query_posts()
过于简单并且存在问题,通过用查询的新实例替换页面的主查询来修改主查询。相对来说这个函数效率较低下(re-runs SQL查询),并在某些情况下可能会彻底失败(特别是在处理帖子分页时)。任何当前的WP代码都应该使用更可靠的方法,例如使用pre_get_posts
挂钩。 长话短说尽量不要使用 query_posts();get_posts()
在用法上非常相似,并且接受相同的参数(具有一些细微差别,如不同的默认值),但返回帖子数组,不修改全局变量并且可以安全地在任何地方使用;WP_Query
类既支持后台默认流程,也可以自己创建和使用它的对象。用法更复杂,限制更少,也可以安全地在任何地方使用。
次佳解决思路
query_posts
– 您永远不应该使用query_posts
。除了上文所说的,query_posts
真正的大问题是,它破坏了主查询对象(存储在$wp_query
中)。很多插件和自定义代码都依赖于主查询对象,因此打破主查询对象意味着您打破了插件和自定义代码的功能。主函数影响分页功能,所以如果你打破了主要查询,就会破坏分页。
要证明query_posts
有多糟糕,请在任何模板上执行以下操作并比较结果
var_dump( $wp_query );
query_posts( '&posts_per_page=-1' );
var_dump( $wp_query );
get_posts
和WP_Query
是构建辅助查询(如静态首页上的相关文章,滑块,精选内容)的正确方法。应该注意的是,不应该在主页,单页或任何类型的归档页面上使用两者中的任何一个,因为它会破坏页面功能。如果需要修改主查询,请使用pre_get_posts
来完成,而不是自定义查询。 (更新:对于静态首页和真实页面,请参阅Using pre_get_posts on true pages and static front pages *)
实质上,WP_Query
由主查询使用,也由get_posts
使用,但虽然get_posts()
使用WP_Query
,但有一些差异
get_posts
比WP_Query
更快。区别取决于网站的总帖子数量。原因是,get_posts
默认将'no_found_rows' => true
传递给WP_Query
,WP_Query
会跳过/合法地中断分页。使用'no_found_rows' => true
,WP_Query
获取查询的帖子数量,然后保留,默认情况下,它会进一步搜索与查询匹配的所有帖子以计算分页。因此,get_posts()
只能用于非分页查询。分页get_posts
真的是一个大混乱。WP_Query
应该用于所有分页查询get_posts()
不受被WP_Query
影响的posts_*
过滤器的影响。原因是get_posts
默认将'suppress_filters' => true
传递给WP_Query
get_posts
有几个额外的参数,如include
,exclude
,numberposts
和category
。在传递给WP_Query
之前,这些参数会变为WP_Query
的有效参数。include
变为post__in
,exclude
变为post__not_in
,category
变为cat
,numberposts
变为posts_per_page
。只需注意,可传递给WP_Query
的所有参数均可与get_posts
一起使用,可以忽略并不使用get_posts
的默认参数get_posts
只返回WP_Query
的$posts
属性,而WP_Query
返回完整的对象。当涉及条件,分页和其他可用于循环内部的有用信息时,该对象非常有用。get_posts
不使用循环,而是使用foreach
循环显示帖子。另外,默认情况下,没有模板标签可用。setup_postdata( $post )
必须用于使模板标签可用。WP_Query
使用默认情况下可用的循环和模板标签get_posts
将'ignore_sticky_posts' => 1
传递给WP_Query
,因此get_posts
默认忽略粘性帖子
基于上述情况,是否使用get_posts
或WP_Query
取决于您,您在查询中实际需要什么。以上应引导您选择
第三种解决思路
基本区别在于query_posts()
实际上只是用于修改当前循环。一旦你完成了,有必要重新设置循环并将其快速发送。这个方法也比较容易理解,因为你的”query”基本上是一个URL字符串,你传递给函数,如下所示:
query_posts('meta_key=color&meta_value=blue');
另一方面,WP_Query
更像是一种通用工具,更像是直接编写MySQL查询,而不是query_posts()
。你也可以在任何地方使用它(不只是在循环中),它不会干扰任何当前正在运行的后期查询。
第四种思路
根本不需要使用query_posts()
。它所做的就是实例化一个新的WP_Query对象,并将该新对象重新分配给global wp_query
。
作为参考,以下是实际的query_posts()
功能。
function query_posts($query) {
$GLOBALS['wp_query'] = new WP_Query();
return $GLOBALS['wp_query']->query($query);
}
如果要创建深度自定义查询脚本,请实例化您自己的WP_Query对象。或者使用get_posts()
,如果你需要做的只是一些轻微的操纵。
参考资料