Understanding how to alter the main query and how to create custom queries in WordPress are two essentials for WordPress developers. You should familiarize yourself with a few things right away:
- What is the
WP_Query
class, including creating new custom queries for secondary loops - Never use
query_posts()
- Alter queries with the
pre_get_posts
hook
You also need to watch WordPress Lead Developer Andrew Nacin talk about WP_Query
in depth in this WordPress.tv Presentation. Seriously, take notes. Follow the slides. Repeat parts multiple times. It might be the best hour you’ll ever spend learning about WordPress.
Now, let me add a couple relatively unimportant points (in comparison) to the above resources on querying with WordPress.
You probably don’t need wp_reset_query()
As Nacin points out in the video above, wp_reset_query()
unsets the main $wp_query
variable, then resets it to the value of $wp_the_query
, and then runs wp_reset_postdata()
. Well, if you’re not using query_posts()
, then you really shouldn’t be messing with the main $wp_query
variable, as wp_reset_query()
does.
All you need to do after a custom WP_Query
is use wp_reset_postdata()
, which resets various global post variables to their original values.
Don’t use $wp_query
to store your custom query information
The other aggravating thing I see in a lot of custom WP_Query
instances, is people storing the main $wp_query
variable temporarily under a new name, and then using $wp_query
to store their custom query information, before resetting $wp_query
back to its original value at the end of the query. This is completely unnecessary and scary.
All it takes is one bad copy / paste for this to cause you many headaches. Please, for all that is good, just assign your custom query to its own variable. Just for fun, I often store mine as $krogsquery
, because I’m pretty sure that’s not going to mess with anyone else’s globals.
Here’s a sample of these two previous items in a WP_Query
that’s not setup properly:
[gist id=”5915706″]
I assume the reason people sometimes override the main query variable this way is because they think they need to in order to call items like have_posts()
and other conditionals. As Nacin points out in his talk, you have access to all of those as methods of your new WP_Query
already, and should call them that way (I actually am calling have_posts()
this way in the query above). And again as Nacin points out, those functions are just calling the methods of the main WP_Query
to start with.
A sample WP_Query
done right
So, here’s a sample WP_Query
that you can utilize for your custom loops that uses a custom variable name and properly resets post data.
[gist id=”5915715″]
It’s not the end of the world if you’ve been doing what I describe above. Not using query_posts()
is a good start toward improving your life as a WordPress developer. But these are a couple of common bits of code I see in custom loops out there that I thought I’d try and help us all do better on.
Seriously, have I mentioned you should watch Nacin’s presentation?
I’ve heard back and forth that for whatever reason, the use of the $wp_query original variable name is needed for pagination with custom post types. However, I can’t confirm. It’d be awesome if someone who knew definitively would chime in regarding that.
So for example in a custom page template wp_reset_query() should be wp_reset_postdata()?
https://github.com/samikeijonen/eino/blob/master/page-templates/download-page.php#L53
Yes. For pagination to work, it must be the main query. That means the best route to alternate a loop on CPT pages would be pre_get_posts().
Great, great, great resource. Adrew is a great speaker. This video is very helpful.
WP_Query( $args ) = wp_reset_postdata();
AND
query_posts ( $args ) = wp_reset_query();
😀
Can you write another WP_Query() snippet with pagination please? You suggest not to reassign the main $wp_query Is there another way to do it?