Why Use pre_get_posts to Modify Queries Instead of query_posts

The query in WordPress is a quite exciting and big topic but to understand it is mandatory for both plugin and theme developers. In this short post, we are going to cover the filtering.

I’m sure that all of us met with the query_posts function and most of us used it in the wrong way like me.

The mentioned common misuse is to altering the main query like to exclude a specific category and so on; this is wrong because it doesn’t filter it but make a new query which can causes a lot of problems later (like pagination error).

query_posts( '&posts_per_page=-1' );

while ( have_posts() ) : the_post();
    the_title();
endwhile;

wp_reset_query();

In this example we modified the posts_per_page value to -1 – I mostly used it for this purpose – to show all of the posts on the same page. Although it seems that we only modified the query we made a new one which isn’t too useful. The basic rule about query_posts is that never to use it, use the alternatives instead.

If you interested more info about it, please visit the Codex!

By default we handle two types of queries in WordPress:

  1. the main which is served by URL,
  2. the secondary which is usually an additional list in the sidebar or somewhere.

Alter The Main Query with pre_get_posts

If we want to modify the main query we have to use the pre_get_posts hook. Using this action, we can access the $query object and change it.

function exclude_category( $query ) {
    if ( ! $query->is_main_query() )
        return;

    if ( ! $query->is_home() || is_admin() )
        return;

    $query->set( 'posts_per_page', '-1' );
}
add_action( 'pre_get_posts', 'exclude_category' );

As you see in this example, it is easy to use. First, we have to check that we alter the correct query with the:

  1. is_main_query – we access just the primary, default query,
  2. is_home – we only run this on the home page,
  3. is_admin – we don’t run this on any admin page.

We can set the parameters with the set() function declaring a name and a value pair. The full parameter list comes from the WP_Query object and we can handle any condition if needed to target something specific.

For more example, please visit the Codex!

What About with The Secondary Queries

For secondary queries – anything that differs from the default WP query – use WP_Query and get_posts(); these two are the same but the second one gives back a usual array of object.

To understand how the query functions work check out this illustration from Andrey “Rarst” Savchenko.

// Using get_posts()

$args = array( 
	'posts_per_page' => 3,
	'category' => 1
);

$posts = get_posts( $args );

foreach( $posts as $post ) :  setup_postdata($post);
    the_title();
endforeach; 

wp_reset_postdata();

Special thanks for the following recource(s): Icon made by itim2101 from www.flaticon.com
Need a web developer? Maybe we can help, get in touch!