Pippins Plugins
  • Email
  • Facebook
  • Feedburner
  • Github
  • Google
  • Twitter
  • Vimeo
  • Youtube
  • Rss
  • About
  • News
  • Join the Site
    • Member Benefits
    • Member Plugins
    • Email Notifications
  • Plugin Store
    • Affiliate Area
    • Checkout
  • Plugins
    • Plugin Portfolio
      • Plugin Portfolio – List View
    • Free
    • Premium
    • Member Plugins
    • Coding Standards
    • Get Plugin Support
  • Tutorials
    • Series
      • Plugin Development 101
      • Creating a User Follow System Plugin
      • Customizing Restrict Content Pro
      • Displaying Content with Easy Content Types
      • Writing Your First WordPress Plugins, Basic to Advanced
      • Working with Widgets
      • User Submitted Image Galleries
      • Plugin Thoughts
      • Integrating Stripe.com with WordPress
      • WordPress Rewrite API
    • Member Exclusive
      • Free Members
      • Subscriber Only
    • Difficulty
      • Beginner
      • Intermediate
      • Advanced
    • Action and Filter Hooks
    • Ajax
    • Custom Post Types
    • External APIs
    • Short Codes
    • Taxonomies
    • Video Tutorials
    • Widget Tutorials
    • WordPress Admin / Dashboard
    • Working with jQuery
    • WordPress Database
    • Writing Plugins
    • Tag Index
  • Reviews
  • Support Forum
  • Contact
    • Support the Site
    • Request Code Review
    • Plugin Support

Using pre_get_posts to Modify Queries for Meta Data and More

Posted on June 27, 2012 by Pippin in Action and Filter Hooks, Advanced, Member Restricted, Subscriber Only, Tutorials, Video Tutorials 24 Comments
Home» Tutorials » Action and Filter Hooks » Using pre_get_posts to Modify Queries for Meta Data and More
Tweet
Love It - 0

There are a lot of ways to query posts in WordPress and a lot of parameters you can use for pulling in just the data you want. For example, you can easily pull in just posts that are in category X, Y, or Z, and you can also just as easily pull in only posts that have a particular meta field set to some value or other. This tutorial video is going to focus on demonstrating the correct way to modify queries and also show how to easily query posts based on meta fields.

One of the worst mistakes that many, many developers make (I’ve been guilty of it countless times) is using query_posts() to modify the main query. One particular example I can think of is using query_posts() in search.php to modify the search results.

Another “crime” that a lot of developers, myself included, are guilty of is modifying queries with a disregard for other queries that might be running on the page. For example, a lot of theme developers like to add an option to their admins for controlling the number of posts displayed on archive pages. A lot of times what happens here is the custom posts_per_page parameter the developer sets overrides ALL queries on the page. I’ve seen this happen several times with my Sugar FAQs plugin; the posts_per_page parameter set by the theme overrides the posts_per_page set in the get_posts() query for the FAQs, so instead of showing 15 questions, the short code only shows 5.

There are many other “crimes” that get committed when queries are involved, but we don’t need to go through. Suffice it to say that the correct way to modify queries anywhere on your WordPress site is through the pre_get_posts action hook (also available as a filter).

Discussed in depth in the video, the pre_get_posts action allows us to easily modify queries anywhere on the site. Here is a quick example of how to force the front page to only show posts that have a meta key called “ecpt_color” that is set to a value of “green”.

1
2
3
4
5
6
7
8
9
10
11
function pw_filter_query( $query ) {
 
	if( is_front_page() && is_main_query() && $query->query_vars['post_type'] != 'nav_menu_item' ) {
 
		$query->set('meta_key', 'ecpt_color');
		$query->set('meta_value', 'green');
 
	}
 
}
add_action('pre_get_posts', 'pw_filter_query', 9999);
Signup as a premium subscriber to gain full access to the video.
Join Now for $6
Tweet Follow @pippinsplugins
add_action, pre_get_posts

24 comments on “Using pre_get_posts to Modify Queries for Meta Data and More”

  1. yellowhousedesign says:
    June 27, 2012 at 4:04 pm

    I’m so glad you published this tut, exactly what I was looking for. Now all I’ll do is hook-up a little front-end form for users to choose their filter options and I’ll be in good shape! Looks like pre_get_posts() doesn’t have sort options – so I may need to dig into that a bit more (it’s saying use query_posts() for that). Thank you again very much!

    Reply
    • Pippin says:
      June 27, 2012 at 5:44 pm

      You mean sort options for setting the order items are displayed? Or what they are sorted by?

    • Pippin says:
      June 27, 2012 at 5:45 pm

      See Paul’s comment below. Is that what you’re referring to?

    • yellowhousedesign says:
      June 27, 2012 at 6:08 pm

      I believe so – ill give that a shot — I need to sort by a meta value as well, so I’ll take another look at how that is done in the tut. Thanks!

    • Pippin says:
      June 27, 2012 at 6:10 pm

      You shouldn’t have any problems sorting by a meta value. Use sort=meta_key and orderby=meta_value.

      If your meta values are numeric, then use orderby=meta_valu_num

  2. paul says:
    June 27, 2012 at 4:34 pm

    so do yo uknow the reason why on the codex, one example uses query->set and the other changes the query_vars object?
    for example to change the post order, I used this
    https://gist.github.com/2995754

    Reply
    • Pippin says:
      June 27, 2012 at 5:45 pm

      I really don’t know. As far as I know, they do exactly the same thing.

    • Pippin says:
      June 27, 2012 at 5:52 pm

      Exploring Core a bit I think I’ve found the answer.
      $query->set() is defined as this:

      1
      2
      3
      
      function set($query_var, $value) {
      	$this->query_vars[$query_var] = $value;
      }

      So that means that $query->set() is doing nothing more than assigning what you pass to the query_vars array.

      We could use $query->get() for doing the same thing as $query->query_vars['parameter'] with $query-&t;get(), which is defined as this:

      1
      2
      3
      4
      5
      6
      
      function get($query_var) {
      	if ( isset($this->query_vars[$query_var]) )
      		return $this->query_vars[$query_var];
       
      	return '';
      }

      So no, there is really no difference at all.

    • Brady Vercher says:
      June 27, 2012 at 6:24 pm

      Aside from the two methods mentioned, there’s actually a third function to do the same thing: set_query_var( $var, $value ).

    • Pippin says:
      June 27, 2012 at 6:27 pm

      Oh that’s cool. It’s the companion to get_query_var(). That’s nice because you can use it outside of pre_get_posts, though you’d have to be careful with that.

    • Brady Vercher says:
      June 27, 2012 at 11:01 pm

      That’s what I was thinking regarding using it outside of pre_get_posts. I was just told that the WP.com theme team recommends using the set() method over the set_query_var() function within pre_get_posts, which makes sense since you have access directly to the object reference. If it’s just to save the overhead of the function call, it seems like the direct assignment method would be preferable.

    • Stephen Harris says:
      June 29, 2012 at 9:53 am

      Brady Vercher mentioned set_query_var. You should avoid using this as it applies only the global $wp_query. pre_get_posts is applied to every WP_Query (and sometimes get_posts). So if you only want to alter the main query, ensure to check the is_main_query method. Using $query->set() has the advantage of modifying secondary queries too (if this is desired).

      @Pippin – typo in the code? is_main_query should be $query->is_main_query

    • Pippin says:
      June 29, 2012 at 9:56 am

      Yeah, you’ll need to be very careful with set_query_var().

      No, I don’t think that’s incorrect. You only have to use $query->is_main_query when using the pre_get_posts filter. Then action accepts all regular conditional tags. I could be wrong though.

    • Stephen Harris says:
      June 29, 2012 at 10:06 am

      So you need to use the $query->is_main_query in pw_filter_query? The method $query->is_main_query checks if $query matches the original query: $wp_the_query. The function is_main_query checks if the global $wp_query matches the original query $wp_the_query. (So, should return false if query_post is used and not reset after wards).

      For instance, in your example with pw_filter_query that should effect all secondary queries on the front page too.

  3. yellowhousedesign says:
    June 28, 2012 at 11:30 am

    Hey Pippin,
    Just doing some more testing — running the following: http://pastebin.com/k6sLishJ I’m using this to set a front-end URL parameter equal to ‘post_type=THE_POST_TYPE’ and it seems to work for everything but pages. One more interesting aspect is that if you look at the print_r() of $query->query_vars that I have output in that function, you’ll see that when you set the URL paremeter to &post_type=page (like http://localhost/wordpress/?s=test&submit=Search&post_type=page for example) the post_type query variable is missing.

    Right now what I have to do as a workaround is http://pastebin.com/c1mUNHKu which seems kinda silly – any thoughts? Thanks!

    Reply
    • Pippin says:
      June 28, 2012 at 12:42 pm

      That first code is not going to do anything. Your $query->set() function is doing nothing more than setting the post_type var to itself, the existing post type var. You should just use the $_GET method in the second one. No need for the If/ELSE, just use the code in the ELSE.

    • yellowhousedesign says:
      June 28, 2012 at 1:05 pm

      Appreciate it Pippin – it looks like when I use the following http://pastebin.com/U1Rjs36X everything works as expected (even pages), but does show the following error when I filter by pages ‘Undefined index: post_type’ which goes back to the original issue – seems kinda weird that when I set it to pages it would show that error. Thanks.

    • Pippin says:
      June 28, 2012 at 1:22 pm

      I think I know why. You are using add_filter() instead of add_action(). The add_filter() method of using pre_get_posts requires that you return the $query;

  4. yellowhousedesign says:
    June 28, 2012 at 1:34 pm

    Bleh – think I’m getting the same thing after trying a few variations. If you just so happen want to nail this in the ground, hit me up on skype :)

    Reply
  5. stomp says:
    June 29, 2012 at 9:28 am

    Hey Pippin,

    I’ve been trying this technique on my site which uses your Events plugin. Basically in the events archive I just want to show future events.

    I’ve tried this but a little lost now…

    https://gist.github.com/3018263

    Cheers,
    Steve

    Reply
    • stomp says:
      June 29, 2012 at 9:39 am

      Pippin – Actually don’t waste your time. I should have looked in your code and worked it out from there. Here’s the complete query for anybody who wants run a pre_get_posts meta query.

      https://gist.github.com/3018263

      It’s for Pippin’s Sugar Events Calendar too ;-)

    • Pippin says:
      June 29, 2012 at 9:41 am

      Yep that should work just fine :)

  6. chrismccoy says:
    July 1, 2012 at 12:17 pm

    nice tutorial, i did this recently instead of doing custom queries ;)

    Reply
    • Pippin says:
      July 1, 2012 at 8:34 pm

      That’s how they should be done :) Thanks Chris!

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

  • Login

Lost your password?

Please enter your username or e-mail address. You will receive a new password via e-mail.

  • Facebook Become a Fan Like

  • Twitter Subscribe on Twitter Follow

  • YouTube Follow my Videos Subscribe

  • RSS Feed Subscribe with RSS Subscribe

Easy Digital Downloads

Most Loved

  • Love It Pro for WordPress
  • Write a “Love It” Plugin with Ajax to Let Users Love Their Favorite Posts / Pages
  • Simple Notices Pro Plugin for WordPress
  • User Bookmarks for WordPress
  • Front End Registration and Login Forms Plugin

Similar Plugins and Posts

  • Plugin Development 101 – Intro to Actions
  • Let’s Talk Extensible Code
  • Create a Live Search in WordPress with jQuery and Ajax
  • Adding Custom Fields to the Easy Digital Downloads Checkout
  • Custom Front End Post Submission Form

Latest Premium Content

  • Plugin Development 101 – Introduction to Adding Dashboard Menus
  • Plugin Development 101 – Intro to Loading Scripts and Styles
  • User Follow System – Part 5
  • Plugin Development 101 – Intro to Short Codes
  • Plugin Development 101 – Registering a Custom Post Type
  • Plugin Development 101 – Intro to Actions

Latest Tutorials

  • Submitting Your First Pull Request to a WordPress Plugin on Github (2)

    Github is an extremely popular tool for managing WordPress plugins, and one...

  • Plugin Development 101 – Introduction to Adding Dashboard Menus (1)

    Adding new menus, both top level and sub level, to the WordPress Dashboard is a really common task for plugins...

  • Plugin Development 101 – Intro to Loading Scripts and Styles (16)

    In this part of Plugin...

Enter your email to receive automated updates when new posts are published

Latest Tweets

  • @jaredatch @kimparsell :D
    May 23, 2013
  • @jaredatch there is, as long as there is at least one ticket
    May 23, 2013
  • RT @Astoundify: We are hiring p/t tech support rep for our support forum if your interested email contact [at] http://t.co/bcXNhcwZx5
    May 23, 2013

Topics

hook meta box Rémi Corson featured shortcodes campaign monitor add_options_page register_setting Sugar Event Calendar attachments add_shortcode wp_enqueue_script the_content image forms short codes Related posts login do_action authors mail chimp attachment plugin recent posts comments post types bbpress apply_filters short code taxonomies custom post type Ajax images gallery Stripe jquery taxonomy users widgets add_filter easy content types add_action widget restrict content pro easy digital downloads

Weekly Newsletter

Useful Links

  • Join the Site
  • Plugin Store
  • Affiliate Area
  • Tag Index
  • Support the Site
  • Suggest a Tutorial
  • Random Post
  • Contact

Monthly Archives

(c) 2011 Pippin's Plugins