I've a custom page template where I want to query 2 posts from a post type and 1 post from another post type. I have it set up like this:

$paged = get_query_var('paged') ? get_query_var('paged') : 1;

$articles = get_posts(array(
  'post_type' => 'articles',
  'numberposts' => 1,
  'posts_per_page' => 1,
  'paged' => $paged

$news = get_posts(array(
  'post_type' => 'news',
  'numberposts' => 2,
  'posts_per_page' => 2,
  'paged' => $paged

$all_posts = array_merge($articles, $news);

Then I do the loop:

<? foreach ($all_posts as $post): setup_postdata($post) ?>
  <? get_template_part('content') ?>
<? endforeach ?>

And finally I add pagination. I tried WP-PageNavi as well as regular WordPress functions.


When I go to the page I can see 3 posts as expected (1 article, 2 news) but there is no pagination. If I manually navigate to /page/2, /page/3, etc. it seems to work and show the next 3 posts but only the previous_posts_link shows up, not the next_posts_link or PageNavi.

The real world example is slightly more complicated and query_posts or WP_Query are not an option.

How to get pagination working properly?

  • 1
    pagination functions operate on the global $wp_query, WordPress has no knowledge of your custom queries and how many pages should exist, and wp_pagenavi needs a query object to read the max_num_pages. I think you'll have to build your own pagination from scratch based on the total number of posts available within each distinct query by querying via WP_Query to know how many posts are available to each query regardless of page. – Milo Mar 21 '13 at 15:48
  • Why does page/2 page/3 work then... – elclanrs Mar 21 '13 at 20:43
  • because adding a page number causes the global paged var to contain that number. the previous_posts_link function simply subtracts 1 from the value of paged. but the default query has no pages, which is why you never see a next_posts_link. – Milo Mar 21 '13 at 21:22
  • @Milo. That's starting to make sense... – elclanrs Mar 21 '13 at 21:42

Your $paged variable on the first is set in the main query. And there is just one page, because it is a page. The get_posts() calls don't affect that. So the number of all available pages is never higher than the current page, and you cannot get a next page link.

Solution: filter pre_get_posts and set your post types here.

  • pre_get_posts doesn't work for me in page templates. I tried the simplest example with The Loop in page-mypage.php and then if (is_page('mypage')) { $query->set('post-type', array('articles','news')); } and it doesn't work. – elclanrs Mar 21 '13 at 21:50
  • This is similar to my problem but there's no asnwer stackoverflow.com/questions/15015316/… – elclanrs Mar 21 '13 at 21:54
  • Also found this which is similar as well wpaustralia.org/topic/pre_get_posts-and-is_front_page. So I'm guessing checking for is_page doesn't work in pre_get_posts so I'm doing this $query->get('pagename') == 'mypage' and then set the query but still doesn't work. – elclanrs Mar 21 '13 at 21:58

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.