I’ve a very simple index.php:

<div id="content">
  <? get_template_part('content', get_post_format()) ?>
</div>

<div id="pagination">
  <? previous_posts_link() ?>
  <? next_posts_link() ?>
</div>

And my content.php looks roughly like this:

<?
$paged = get_query_var('paged') ? get_query_var('paged') : 1;
query_posts([
  'post_type' => ['articles', 'projects', 'tips'],
  'orderby' => 'date',
  'posts_per_page' => 7,
  'paged' => $paged
]);
?>

<? while(have_posts()): the_post() ?>
  <article class="post">
    <h2><? the_title() ?></h2>
    <p><? the_excerpt() ?></p>
    <ul>
      <? foreach($categories as $cat): ?>
      <li class="category"><a href="#"><?= $cat->name ?></a></li>
      <? endforeach ?>
    </ul>
  </article>
<? endwhile ?>

There are 14 posts in total but the “next” posts is always redirecting to a 404 on /page/2 instead of showing the remaining 7 posts.

Edit: If I use a custom WP_Query instead of query_posts then the next and previous links won’t even show. https://gist.github.com/elclanrs/4782705

I’ve been trying to find a solution to this issue since yesterday. I’m aware of all the other questions similar to this one, but for my particular set-up none of the solutions I found worked, including:

  • http://wordpress.org/support/topic/pagination-with-custom-post-type-listing
  • http://www.rjust.com/2011/03/22/fix-previous_posts_link-and-next_posts_link-for-custom-post-types/
  • Make sure that “Blog pages show at most” matches posts_per_page

I’m also aware of pre_get_posts but I would like to know what’s the problem with my current setup. Any ideas?

2 Answers
2

By the time you reach the template, WordPress has already queried the database and decided what to display based on those results.

You’re seeing a 404 error because based on the default main query, there are no more posts to show.

When you call query_posts in the template, you overwrite that original query. Despite the fact that your new query results contain more posts, WordPress has no awareness of this modified query.

This is why you should never use query_posts in the template. You’ve provided the solution to your issue already, use the pre_get_posts action to modify the main query before it happens.

Leave a Reply

Your email address will not be published. Required fields are marked *