img Hey! I'm a French WordPress developer! Welcome on my site!
  • Follow me:
Modifying the current query with pre_get_posts
27th Jan

2013

Modifying the current query with pre_get_posts

Pre_get_posts is a hook

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.

Targeting the main query

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();

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.

Going a bit further

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:

Conclusion

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!

Share This :

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!

Comments

Gilles Vauvarin

2013-02-10 10:10:35 Reply

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 ?

    Rémi

    2013-02-10 18:00:59 Reply

    Hi Gilles, not exactly. Actually, you can increase the number of parameters to send to the query, not just resuming the query. So, the main aim is to modify the query by adding or deleting parameters.

Grant

2013-02-18 00:29:57 Reply

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!

    Rémi

    2013-02-18 07:16:00 Reply

    Hi Grant, i don’t think you need to use pre_get_post for what you need. I guess that a simple new WP_Query should do the job.

Grant

2013-02-18 08:09:48 Reply

Thanks Remi, got it working with a new WP_Query that sets the tax term dynamically: http://pastebin.com/nzBWd5tL

Leave a Comment

Your email address will not be published.