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...


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;
| improve this answer | |
  • Very nice trick! – Anh Tran Sep 21 '11 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 Oct 7 '11 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. – MikeSchinkel Oct 8 '11 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 Jan 17 '18 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. :)

| improve this answer | |
  • 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 – onetrickpony Sep 16 '11 at 3:44
  • Updated my answer with the custom loops answer. – Brian Fegter Sep 16 '11 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. – MikeSchinkel Sep 16 '11 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. – Brian Fegter Sep 16 '11 at 5:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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