pre_get_posts instead of query_posts

The other day I had a custom content type of things for sale.  There’s a meta field for marking it Sold.  On my archive page I didn’t want to include Sold items, so I went hunting for the proper query_posts() bit to put in the top of my archive template.

What I found was several posts that said to never ever use query_posts().  The reason is that it doesn’t actually change the query like I thought it did, it simply runs another one.  However successful that may be at getting your content, it’s a second database query you don’t want.

The answer is to use a filter called pre_get_posts, and just like it sounds, it allows you to do stuff before you get posts.

So here’s what I did:

function filter_sold_coaches( $query ) {

    // check to see if we're editing the main query on the page.
    if( $query->is_main_query() ){

        // Check to make sure I'm on the Coaches archive page OR the Make page AND I'm not in the admin area
        if ( ($query->is_post_type_archive('coaches') OR $query->is_tax('make')) AND !is_admin() ) {

            // set a meta query to get only Coaches where the ecpt_sold element does not exist.
            $query->set('meta_query',array( array( 'key' => 'ecpt_sold', 'value' => 'on', 'compare' => 'NOT EXISTS')));

            // now I want to order by the year field, so I do that
            $query->set('meta_key', 'ecpt_coachyear');
            $query->set('orderby', 'meta_value_num');
        }

    }
    return $query;

}
// now I apply my function to pre_get_posts and Bob's your uncle
add_filter( 'pre_get_posts', 'filter_sold_coaches' );

The !is_admin bit is important, because this will affect your admin area if you don’t and you’ll find that you’re missing some posts.

Using the set() method you can set anything that you migth set with WP_Query, so if you’re good with that then this should be quite easy for you.

Many thanks to @pippinsplugins for wisdom in putting this together.

Leave a Reply

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