Understanding The Difference Between query_posts and WP_Query
Does it really matter which you use?
According to the WordPress Codex, there is actually a distinct difference between WP_Query() and query_posts(), as for when and where you should use one of the other and when you shouldn't.
Here's what it says:
The query_posts() function is intended to be used to modify the main page Loop only. It is not intended as a means to create secondary Loops on the page.
If you want to create separate Loops outside of the main one, you should create separate WP_Query() objects and use those instead.
Use of query_posts() on Loops other than the main one can result in your main Loop becoming incorrect and possibly displaying things that you were not expecting.
What does that mean?
It isn't entirely clear what the main page loop is, or what the other loops are that WordPress uses. Let me try to explain for those that don't get it.
The Main Page Loop And query_posts
On average, all of the main theme template files, index.php, single.php, page.php, etc., will more than likely contain a piece of code at the beginning that looks something like this:
<?php if ( have_posts() ) : ?> <?php while ( have_posts() ) : the_post(); ?>
Then somewhere further down in the code there is an endwhile;endif; which will end the while loop and the if respectively. That is what makes the main page loop.
To use query_posts() you just place it before The Loop begins. The wp_query object will generate a new SQL query using the parameters which you define.
You should note that WordPress includes certain settings that can control how the loop is generated, which can potentially interfere with any custom queries which you create.
The "Blog pages show at most" parameter in Settings > Reading can influence your results. To overcome this, add the 'posts_per_page' parameter to your query.
For other ways to use query_posts() here are some examples.
Creating Custom Loops and WP_Query
I will only go over this quickly since I have previously written a tutorial on how to use WP_Query() to create custom loops. So you can refer to that for more information if needed.
If you need to create a custom loop on a page that already has the main loop that I went over above, or in other words a separate loop, you need then use WP_Query() to create a separate wp_query object. The reason this is important is so you don't end up somehow changing or otherwise interfering with the main loop used in that page. Think of WP_Query as an instance, or a copy of the object. To create a loop that should use this object for displaying something different, you need to create a new copy of it so you don't screw up the more important one which most likely generates the main content of that page.
Both the WP_Query() object and query_posts() are created in /wp-includes/query.php of the WordPress source. Try using the Php Cross Reference to search the core further.
Confused yet? It's a somewhat difficult thing to explain, so if you have any questions about this then please leave a comment and I can better explain anything you are unclear about. All comments are welcome (except spam).







User Comments
( ADD YOURS )Rarst June 23
Even better variant is get_posts() function. It takes same parameters as query_posts(), doesn't interfere with other loops and takes care of handling WP_Query object.
Codex describes it specifically as function to create multiple loops.
I wonder why this function is so desperately under-known. :(
Jared June 23
Thats a good point, I should've included that in this post.
Thanks for pointing it out here. :)
Eric Curtis June 25
On my homepage I am excluding a custom post type from showing in the main loop but I do want to have it show in the side bar.
But when I run WP-Query those posts do not appear. Is that because WP_Query makes a copy of the main loop to work with and by removing that custom post type I can not access it?
If so how do I get a brand new loop and not a copy?
Cheers.
Jared June 25
@Eric: WP_Query is the object which is used to make the loop. query_posts is what makes the main loop out of the main WP_Query object. You are thinking of it backwards.
If you want to create a custom loop for you sidebar for any post type, you would be able to do it like this:
$q = new WP_query();
$q->query( "post_type=YOUR_POST_TYPE_HERE&showposts=5" );
if (have_posts()) :
while ($q->have_posts()) : $q->the_post();
// your code for the loop
endwhile;
endif;
Just put whatever your post type is where YOUR_POST_TYPE_HERE, and the number of posts to show, showposts=5. You could just put this into your sidebar.php file, where you want it to show.
Hope this helps :)
Eric Curtis June 25
That does help. Thank you.
How would I exclude on custom_post_type from appearing in the main loop?
I found this on Justin Tadlocks site but it is messing up other new querys...
add_filter( 'pre_get_posts', 'my_get_posts' );
function my_get_posts( $query ) {
if ( is_home() || is_feed() || is_archive() )
$query->set( 'post_type', array( 'post', 'work', 'opening', 'upcoming' ) );
return $query;
}
...I have another custom_post_type called crew that I do not want showing up in the homepage, feed, search or archive loops...
Jared June 26
Just from looking at that code, your issue is more than likely due to you not wrapping the if statement with curly braces { }. This is how it should be.
function my_get_posts( $query ) {
if ( is_home() || is_feed() || is_archive() ) {
$query->set( 'post_type', array( 'post', 'work', 'opening', 'upcoming' ) );
}
return $query;
}
If that doesn't work, there are other ways too, but that is most likely the problem.
Eric June 26
I worked with a great WP developer (Aaron Jorbin) to figure this out. A couple of things.
1. The function was getting called on pre_get_posts so it was changing the main $posts
2. WP_Query copies that to work with so the custom post type needed for the sidebar was never in the $posts
3. The solution was to use get_posts(); which makes a brand new $posts variable not a copy.
Cheers.
Wordpress Themes June 30
Amiable dispatch and this mail helped me alot in my college assignement. Gratefulness you as your information.
Son.Nguyen July 7
Good
Sathasivam February 24
Hi friends,
How to generate search result only for particular custom post type
John April 12
I am still struggling to understand how queries work with get_posts(), query_posts() and WP_Query().
In particular I do not understand what pre-existing selection may exist when using these on a given page template.
From various blogs seems that the default situation is that query_posts() and WP_Query() apply any pre-existing filters whilst get_posts supresses them.
However the codex says query_posts() ignores other parameters it receives via the URL (such as page number or category.
Are these filters / parameters the same or something different?
How can I definitively tell what pre-existing selection will exist when I create a query?
Trackbacks