Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

It seems like half the tutorials in the Codex and around the blogosphere use query_posts() and half use WP_Query. What's the deal?

share|improve this question

6 Answers 6

up vote 350 down vote accepted
  • query_posts() is overly simplistic and problematic way to modify main query of a page by replacing it with new instance of the query. It is inefficient (re-runs SQL queries) and will outright fail in some circumstances (especially often when dealing with posts pagination). Any modern WP code should use more reliable methods, like making use ofpre_get_posts hook, for this purpose. TL;DR don't use query_posts() ever;

  • get_posts() is very similar in usage and accepts same arguments (with some nuances, like different defaults), but returns array of posts, doesn't modify global variables and is safe to use anywhere;

  • WP_Query class powers both behind the scenes, but you can also create and work with own object of it. Bit more complex, less restrictions, also safe to use anywhere.

share|improve this answer
4  
@jjeaton query_posts() is tiny wrapper function for WP_Query, the only extra thing it does (as per flowchart) is overwriting global $wp_query –  Rarst Aug 8 '11 at 15:39
5  
@jjeaton Replacing query_posts() with WP_Query will make no difference in performance, original page's query will still run because that is part of core load. Those queries will run even if your template file has no loop at all. –  Rarst Aug 8 '11 at 17:15
58  
Can't get rid off the feeling that this the most genious and upvoted post on WPSE. Should be in Codex as well. –  kaiser Sep 16 '11 at 0:03
3  
I'll just add my clearest description of the "performance of query_posts()" issue: Using query_posts() or WP_Query within a template file will have the same performnace cost: the query you just performed. The issue discussed in the codex article is that if you actually want to replace the query you should do so by filtering the original query_posts() with the 'parse_query' filter. That way you only have the one, original, desirable query, rather than doing a second query to awkwardly replace it. query_posts() is NEVER THE WAY!! NEVER! –  jeremyclarke Apr 19 '12 at 22:24
8  
There's a freaking awesome explanation of query_posts written by John James Jacoby on the developer.wordpress.com blog that blows all of these answers out of the water. The main point: query_posts doesn't modify the main loop at all, it replaces it after it has already run. The best way to modify the main loop is through a pre_get_posts filter. developer.wordpress.com/2012/05/14/… –  Dan Gayle Jun 9 '12 at 23:10

The basic difference is that query_posts() is really only for modifying the current Loop. Once you're done it's necessary to reset the loop and send it on its merry way. This method is also a little easier to understand, simply because your "query" is basically a URL string that you pass to the function, like so:

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

On the other hand, wp_query is more of a general purpose tool, and is more like directly writing MySQL queries than query_posts() is. You can also use it anywhere (not just in the Loop) and it doesn't interfere with any currently running post queries.

I tend to use wp_query more often, as it happens. Really, it's going to come down to your specific case.

share|improve this answer

If I recall reading right, essentially "the loop" is doing WP_Queries in the core files, but in an easier to understand way.

share|improve this answer

Make sure that you use wp_reset_query() after using query_posts() because it will affect other query result also.

share|improve this answer

There is simply no need to use query_posts(). All it does is instantiates a new WP_Query object and reassigns that new object to global wp_query.

For reference, the following is that actual query_posts() function.

 function query_posts($query) {
        $GLOBALS['wp_query'] = new WP_Query();
        return $GLOBALS['wp_query']->query($query);
    }

Instantiate your own WP_Query object if you want to create an in depth custom query script. Or use get_posts() if all you need to do is some light manipulation here and there.

In either case, I highly recommend doing yourself a favor and going to wp_includes/query.php and perusing the WP_Query class.

share|improve this answer

I would say don't use get_posts() in a plugin. It imposes very restrictive filters in some cases (set's surpress_filters, ignore_sticky_posts, etc.) and should probably only be used in a theme when you want something done quick.

share|improve this answer

protected by kaiser Feb 11 '13 at 17:08

Thank you for your interest in this question. Because it has attracted low-quality answers, posting an answer now requires 10 reputation on this site.

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.