How can I change arguments for the main query only, and not affect other queries?

add_filter('pre_get_posts', 'custom_post_count');
function custom_post_count($query){
  $query->set('posts_per_page', 5);
  return $query;

Because this action is called inside the get_posts method of WP_Query, this code will alter the posts_per_page argument for all loops, not just the main, so passing this argument to WP_Query is useless...

2 Answers 2


Basically what you are looking for is the global $wp_the_query variable which is set to the value of the main query. It may not be a perfect fit for 100% of cases but will probably work fine in 99% of cases:

add_action( 'pre_get_posts', 'custom_post_count' );
function custom_post_count( $query ){
  global $wp_the_query;
  if ( $wp_the_query === $query ) {
    $query->set( 'posts_per_page', 5 );
  return $query;
  • Very nice trick!
    – Anh Tran
    Commented Sep 21, 2011 at 4:13
  • I think Brian's method is much better. His code is self-documenting and uses the API, whereas this is unintuitive and vulnerable to changes in core.
    – Ian Dunn
    Commented Oct 7, 2011 at 18:45
  • @IanDunn: While it may be less intuitive to you, it is the "official way" to solve this problem. The WordPress team is adding is_main_query() to 3.3 and it uses the same technique. Of course as there are many ways to solve the same problem in WordPress, Brian's solution is a good one too. Just avoid the use of query_posts() in your theme, as noted. Commented Oct 8, 2011 at 5:51
  • I had a problem where if( is_tax('my_custom_tax') && is_main_query()) was firing in a second loop too in the footer, but just on those pages which displayed my_custom_tax in the main query. This solved my problem.
    – D. Dan
    Commented Jan 17, 2018 at 7:34

Firstly, 'pre_get_posts' is an action and not a filter. That's the main problem to start. Secondly, you need to set conditionals for the context.

add_action('wp', 'custom_post_count');
function custom_post_count($query){
    if($query->is_home || $query->is_front_page){
        $query->set('posts_per_page', 5);
    return $query;

The previous example is if you want to use this once in your functions.php without touching your template files. As far as affecting every query, if you don't create a new query, every loop with inherit the pre_get_posts $query. That's why I use query_posts() to create a new query in the following example.

Custom Loops

This is how I do custom loops:

$args = array(
    'posts_per_page' => 5

if(have_posts()): while(have_posts()): the_post();

endwhile; else:



Just place query_posts() above the loop and wp_reset_query() at the end of the loop.

Hope this helps you out. :)

  • These conditionals are set inside custom loops too. For example I could have "recent posts" type of widget. Also, your code will work only if the custom loop is being made before the wp action Commented Sep 16, 2011 at 3:44
  • Updated my answer with the custom loops answer. Commented Sep 16, 2011 at 3:49
  • 3
    @Brian - query_posts() is not really recommended, just fyi. One of the many problems with it is using it causes WordPress to make two database queries when it could have just made one. Commented Sep 16, 2011 at 5:28
  • 1
    Thanks Mike! I never knew the intricacies of this until I looked at your link and Rarst's fab graphic. I appreciate the tip. Commented Sep 16, 2011 at 5:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.