2013
“pre_get_posts” is a WordPress hook that allows you to modify the current query. Just a quick reminder: when you’re visiting any page of a WordPress install, the system creates a query that depends on the url you’re visiting. This is basically what the template hierarchy does. The “pre_get_posts” hook is called after the query variable object is created, but before the actual query is run. That’s why this allows you to modify the query before results are printed on your screen. That’s pretty useful to modify for example an archive page, the results of a search, or a custom post type page. Here’s an info about “pre_get_posts” in the codex:
The pre_get_posts action gives developers access to the $query object by reference (any changes you make to $query are made directly to the original object – no return value is necessary).
That’s important to note that the $query object passed to your function is passed by reference. That’s to say that you don’t need to declare globals variables and you don’t need to return a value. Any changes you make to the object from inside your function are made to the original immediately.
Most part of the time when you access a page on a WordPress website, you’re loading more than queries, thats why it’s important to be aware of the query you want to modify when using “pre_get_posts”. A great method to know it, is to use the is_main_query() update: $query->is_main_query(). Here is what the codex says about is_main_query() function:
This function enables someone to hook into `pre_get_posts` and modify *only* the main query. This is a boolean function, meaning it returns either TRUE or FALSE. NOTE: admin screens also have a main query and this function can be used to detect it there.
NOTE: Mark Jaquith explained me via Twitter that the is_main_query() function must not be used anymore as it’s useless, and the conditional statement should be done through $query->is_main_query();
@remicorson mistake: is_main_query() should be $query->is_main_query(). The is_main_query() *function* is useless and should not be used.
— Mark Jaquith (@markjaquith) 27 janvier 2013
Here is a small example using is_main_query and pre_get_posts:
This code is simply taking off posts from category ID 5 from the main query.
But you can go further, you can for example query only posts from a specific type and with a custom meta field key equal to a determined value. In the code below, we are targeting only custom post type called “portfolio” where meta key “project_type” is set to “design”, that’s a typical query that can be used on a portfolio page:
That’s not all, you can for example define a posts per page number:
You can also define a query that lists posts from a specific date:
And finally here is a sample to display posts older than the current date. This one is a bit more complex, because we need to use the “posts_where” filter:
As we saw, “pre_get_posts” is really powerful and can really helps you to customize the current query. This is also a good method to modify a query made from a plugin without modify the core plugin files (or the theme core files). So i really encourage you to have a deep leep to that hook and use it in your own developments!
Hey! My name is Rémi Corson, i'm a WordPress Expert Developer, i create high level themes and plugins, and i provide free stuff every week on this website!
2013-02-10 10:10:35
Hello Rémi,
Thanks for this short tutorial.
Correct me if I’m wrong but actually the main interest to use pre_get_posts() in our code is to avoid to call an unnecessary new query and thus decrease the number of request on our data base ?
2013-02-18 00:29:57
Thanks for the post Remi,
I’m having a bit of trouble using your method vs. modifying the WP $query directly, wondering if pre_get_posts is what I need or not.
I’d like to filter out posts in a specific archive page where the value for a custom meta field is earlier than todays date. Here’s my code: http://pastebin.com/fS1CyuRR, which works when modifying the WP $query directly, but not when using your pre_get_posts method.
I thought I’d pose the question to see if you have any thoughts! Thanks!
2013-02-18 08:09:48
Thanks Remi, got it working with a new WP_Query that sets the tax term dynamically: http://pastebin.com/nzBWd5tL