WP_Query returns random number of posts

There’s a file called inform.php included in index.php, single.php and single-news.php with the below query in it:

<?php
    $arr = array('cat' => '12837', 'posts_per_page' => '22');
    $query1 = new WP_Query($arr);
    while($query1->have_posts()) : $query1->the_post();
?>
    <li><a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>"><?php the_post_thumbnail("icon-40", array('class' => 'right icon-40')); ?><?php /*<span class="app-name"><?php echo text_excerpt(get_the_title(), 67); ?></span>*/ ?></a></li>
<?php
    endwhile;
    wp_reset_postdata();
?>

It returns exact 22 number of posts in index.php and single.php but in single-news.php it returns only one post.

Read More

There is no difference between single.php and singel-news.php except styling and displaying some custom fields.

Also I checked for wp_reset_postdata(); to be considered after each custom query I wrote, but yet there is that strange result.

Single news template will load by this function:

function custom_cat_single_file($single_template) {
  global $post;
   if ( in_category( 'news' ) && !in_category('mac-game')) {
      $single_template = dirname( __FILE__ ) . '/single-news.php';
  }
  return $single_template;
}
add_filter( "single_template", "custom_cat_single_file" );

Update #1

Reformatted var_dump($query1->request);

string(476) "SELECT SQL_CALC_FOUND_ROWS wp_posts.id 
FROM   wp_posts 
       INNER JOIN wp_term_relationships 
               ON ( wp_posts.id = wp_term_relationships.object_id ) 
WHERE  1 = 1 
       AND ( wp_term_relationships.term_taxonomy_id IN (12837) ) 
       AND wp_posts.post_type = 'post' 
       AND ( wp_posts.post_status = 'publish' 
              OR wp_posts.post_status = 'private' ) 
       AND wp_posts.post_date >= '2014:03:21 00:00:00' 
       AND wp_posts.post_date < '2015:03:21 00:00:00' 
GROUP  BY wp_posts.id 
ORDER  BY wp_posts.post_date DESC 
LIMIT  0, 22"

I’ve a pre_get_post hook but I don’t think it affects something.

function post_in_page( $query ) {
  // not an admin page and is the main query
  if (!is_admin() && $query->is_main_query()){
    if(is_category()){
      $current = get_query_var('cat');
      $cat = get_category ($current);
      if($cat->slug != 'news')
        $query->set('posts_per_page', 25);
    }
  }
}
add_action( 'pre_get_posts', 'post_in_page');

Update #2

As @s_ha_dum noticed about dates, I didn’t found any hooked function however I didn’t go deep in all plugins files.

So I ended up with modifying WHERE clause of query:

function so__weird()
{
  function filter_where( $where = '' ) {
    $where = preg_replace("/ ANDs+wp_posts.post_date.*?wp_posts.post_date.+[^'].*?'/s", '', $where);
    return $where;
  }
  add_filter( 'posts_where', 'filter_where' );
}

and calling so__weird() at the needed place.

Related posts

Leave a Reply

1 comment

  1. There is no reason that query should behave differently on a single post page than on any other page. That is, there is no reason in the code posted. The only thing that I can think of would be that there is a filter interfering– perhaps a poorly written filter on pre_get_posts or post_limits.

    You should be able to verify the SQL coming out of that query with var_dump($query1->request);, and if it ends with anything other than LIMIT 0, 22 you have something interfering.

    Based on additional information in the question:

    The pre_get_posts callback you posted should not, unless I am reading wrong, cause the query to return a single post. It should return more than 22 if anything. However, there are date conditions in that query…

       AND wp_posts.post_date >= '2014:03:21 00:00:00' 
       AND wp_posts.post_date < '2015:03:21 00:00:00' 
    

    … that are not accounted for by your explicit query arguments. There must be another filter somewhere.