Question

I'm having a very peculiar bug with pagination :( I'm trying to display 4 posts per page for a category with slug "lastest-news".

The pagination function seems to work correctly. There are 33 posts. The pagination gets constructed correctly with 9 pages and links of following format: /category/lastest-news/page//

The interesting thing is that it works correctly (displaying 4 posts per page) from page 1-4 including. However, for pages 5-9 it doesn't work at all. It doesn't even seem to serve the template... the only error that I could spot is of the page saying "Nothing found for Category Lastest-news Page 5".

I would understand if it won't work at all, but for randomly 4 pages and not more?

I would really really appreciate any help! I've spend about over 4 hours trying to figure out what's wrong and it's bugging me.

Thanks for help :)

I'm using the following code for query:

<?php 
$page = get_query_var('paged');
$posts_on_page = new WP_Query("posts_per_page=4&category_name=lastest-news&paged=".$page);

//loop to display every one of 4 posts

//pagination
pagination($posts_on_page->max_num_pages);
?>

I'm using pagination function from this post: http://www.kriesi.at/archives/how-to-build-a-wordpress-post-pagination-without-plugin

Here is the function (which seems to work fine):

function pagination($pages = '', $range = 2){  
 $showitems = ($range * 2)+1;  

 global $paged;
 if(empty($paged)) $paged = 1;

 if($pages == '')
 {
     global $wp_query;
     $pages = $wp_query->max_num_pages;
     if(!$pages)
     {
         $pages = 1;
     }
 }   

 if(1 != $pages)
 {
     echo "<div class='pagination'>";
     if($paged > 2 && $paged > $range+1 && $showitems < $pages) echo "<a href='".get_pagenum_link(1)."'>&laquo;</a>";
     if($paged > 1 && $showitems < $pages) echo "<a href='".get_pagenum_link($paged - 1)."'>&lsaquo;</a>";

     for ($i=1; $i <= $pages; $i++)
     {
         if (1 != $pages &&( !($i >= $paged+$range+1 || $i <= $paged-$range-1) || $pages <= $showitems ))
         {
             echo ($paged == $i)? "<span class='current'>".$i."</span>":"<a href='".get_pagenum_link($i)."' class='inactive' >".$i."</a>";
         }
     }

     if ($paged < $pages && $showitems < $pages) echo "<a href='".get_pagenum_link($paged + 1)."'>&rsaquo;</a>";  
     if ($paged < $pages-1 &&  $paged+$range-1 < $pages && $showitems < $pages) echo "<a href='".get_pagenum_link($pages)."'>&raquo;</a>";
     echo "</div>\n";
 }
}
Was it helpful?

Solution

WordPress does its own query on every page. You should modify that query instead of creating a new one. What happens now is that WordPress does a query with the standard posts per page of 10, but you don't do anything with these results and do your own query. This works... until WordPress goes beyond post #33, which is on page number 4.

  1. WordPress queries 1-10, your template queries 1-4
  2. WordPress queries 11-20, your template queries 5-8
  3. WordPress queries 21-30, your template queries 9-12
  4. WordPress queries 31-40, your template queries 13-16
  5. WordPress queries 41-50, but gets no results, so it gives 404. Your template doesn't load.

So instead you should modify the standard query that WordPress will execute, by placing this in your functions.php or in a plugin:

add_action( 'pre_get_posts', 'wpse7687_pre_get_posts' );
function wpse7687_pre_get_posts( &$wp_query ) {
    if ( $wp_query->is_category && 'latest-news' == $wp_query->get_queried_object()->slug ) {
        $wp_query->set( 'posts_per_page', 4 );
    }
}

OTHER TIPS

Based on @Jan Fabry reply I've change the syntax a bit. It works well. Thanks Jan for the explanation!!!

add_action( 'pre_get_posts', 'wpse7687_pre_get_posts' );
function wpse7687_pre_get_posts( &$wp_query ) {
  if ($wp_query->query_vars['category_name'] == 'latest-news'){
    $wp_query->query_vars['posts_per_page'] = 4;
  }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with wordpress.stackexchange
scroll top