什么时候应该使用WP_Query vs query_posts()vs get_posts()?


Answers:


667
  • query_posts()通过用查询的新实例替换页面的主查询,这种方法过于简单和有问题。它效率低下(重新运行SQL查询),并且在某些情况下(特别是在处理帖子分页时,通常会完全失败)。pre_get_posts为此,任何现代WP代码都应使用更可靠的方法,例如利用钩子。TL; DR 永远不要使用query_posts()

  • get_posts() 在用法上非常相似,并且接受相同的参数(有一些细微差别,例如不同的默认值),但是返回的是帖子数组,不会修改全局变量,并且可以在任何地方使用。

  • WP_Query是在后台提供支持的类,但是您也可以创建和使用自己的实例。更加复杂,限制更少,在任何地方都可以安全使用。


8
@jjeaton query_posts()是它的微型包装函数WP_Query,它唯一要做的事情(按照流程图)是覆盖全局$wp_query
Rarst 2011年

7
@jjeaton替换query_posts()WP_Query不会影响性能,原始页面的查询仍将运行,因为这是核心负载的一部分。即使模板文件根本没有循环,这些查询也将运行。
罗斯特(Rarst)2011年

116
无法摆脱这是WPSE上最巧妙和最受好评的帖子的感觉。也应该在食典中。
kaiser

8
我将添加对“ query_posts()性能”问题的最清楚的描述:在模板文件中使用query_posts()或WP_Query将具有相同的性能成本:刚刚执行的查询。Codex文章中讨论的问题是,如果您实际上要替换查询,则应使用“ parse_query”过滤器过滤原始的query_posts()来进行替换。这样,您只有一个原始的理想查询,而不必进行第二个查询来笨拙地替换它。query_posts()永远不可能!决不!
jerclarke'4

22
约翰·詹姆斯·雅各比(John James Jacoby)在developer.wordpress.com博客上对query_posts做出了令人敬畏的惊人解释,使所有这些答案无所适从。要点:query_posts根本不修改主循环,它运行后将替换。修改主循环的最佳方法是通过过滤器。 developer.wordpress.com/2012/05/14/...pre_get_posts
丹·盖尔

65

query_posts-永远不要使用query_posts。除了@Rarst所说的以外,真正的大问题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它,而不是自定义查询。(更新:对于静态首页和真实首页,请参阅在真实页面和静态首页上使用pre_get_posts *)

本质上,WP_Query由主查询使用get_posts,也由所使用,但是尽管get_posts()使用WP_Query,但还是有一些区别

  • get_posts比快WP_Query。保证金取决于网站的总帖子数。这样做的原因是,get_posts通过'no_found_rows' => true在默认情况下WP_Query它跳过/法律上打破分页。使用'no_found_rows' => trueWP_Query获取查询的帖子数量,然后进行纾困,默认情况下,它将进一步搜索与查询匹配的所有帖子,以计算分页。

    因此,get_posts()应仅用于非分页查询。分页get_posts确实是一大麻烦。WP_Query应该用于所有分页查询

  • get_posts()不受过posts_*滤器的WP_Query影响,而受这些过滤器的影响。原因是get_posts默认情况下传递'suppress_filters' => trueWP_Query

  • get_posts有几个像额外的参数includeexcludenumberpostscategory。在将这些参数WP_Query传递给之前,确实将其更改为有效参数WP_Queryinclude被改变成post__inexcludepost__not_incategorycatnumberpostsposts_per_page。请注意,所有可以传递给的参数都可以WP_Query使用get_posts,您可以忽略并且不使用的默认参数get_posts

  • get_posts只返回while $posts属性,返回完整对象。当涉及条件,分页和可在循环内使用的其他有用信息时,此对象非常有用。WP_QueryWP_Query

  • get_posts不使用循环,而是foreach循环显示帖子。另外,默认情况下没有模板标签可用。setup_postdata( $post )必须用于使模板标签可用。WP_Query使用循环,默认情况下模板模板可用

  • get_posts传递'ignore_sticky_posts' => 1WP_Query,因此get_posts默认情况下会忽略粘性帖子

基于以上内容,您是否使用get_posts还是WP_Query取决于您,以及查询实际需要什么。以上应指导您的选择


1
我希望我能喜欢的答案。这解释了很多。
Patrik Alienus

1
很好的解释!“ get_posts()仅应用于非分页查询。将get_posts分页确实是一大麻烦。WP_Query应该用于所有分页查询”基本上是所有需要了解imo的人。
Bullyen

32

基本区别是query_posts()实际上仅用于修改当前循环。完成后,有必要重置循环并以愉快的方式发送循环。仅仅因为您的“查询”基本上是您传递给函数的URL字符串,所以该方法也更易于理解,如下所示:

query_posts('meta_key=color&meta_value=blue'); 

另一方面,WP_Query它更像是一种通用工具,比起直接编写MySQL查询更像是直接编写MySQL查询query_posts()。您还可以在任何地方使用它(不仅在循环中使用),它不会干扰任何当前正在运行的后查询。

WP_Query碰巧的是,我倾向于更频繁地使用。确实,这将取决于您的具体情况。


15

根本没有必要使用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()如果您需要做的只是在这里和那里进行一些灯光操作,请使用。

在任何情况下,我强烈建议做自己一个忙,去wp_includes/query.php和细读WP_Query类。



10

如果我记得没看错的话,本质上“循环”就是WP_Query在核心文件中进行的,但是以一种更易于理解的方式进行。


6
  • query_posts():如果需要修改主查询,可能仅在一种情况下使用。它设置了很多全局变量。
  • get_posts():在机制上非常相似,并且接受相同的参数,但是返回帖子数组
  • WP_Query:您可以创建和使用它自己的对象。位更加复杂,限制更少,可以在任何地方安全使用。

-6

我会说不要get_posts()在插件中使用。它规定在某些情况下非常严格的过滤器(设置的suppress_filtersignore_sticky_posts等等),并应可能只在一个主题时,你想要的东西做快速使用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.