Multiple WordPress loops with working pagination

I have a WordPress site that uses multiple category formats requiring up to 3 loops. Many sites and themes use multiple loops on the homepage, but homepages for a newspaper are generally not paged. Since we were using multiple loops on bottom level categories, they had to be paged and we didn’t want any duplicates to appear.

You cannot use offset within a paged loop, because that will break your pagination. Every method I found to remove posts from the standard loop would cause the pagination to break. This is because you cannot use offset with pagination.

Also, it should be noted that on our site, only the category index display the first two loops.

Sites Category Structure:

  • Loop 1 – 1 post, with tag “mainfeature”
  • Loop 2 – 5 posts, excluding tag “features”
  • Loop 3 – 6 posts, offset by 5 and excluding post with tag id 136

Loop 1 lets us display a featured post. Loop 2 displays the 5 most recent posts, and Loop 3 displays the next 6 posts and contains the pagination.

Solution

Create a list of post id’s to exclude from the loop containing pagination. Using offset simply will not work. Within each loop we will add the retrieved posts to an array.

First 2 Loops:

Your first two loops should contain $posts_exclude[] = $post->ID

<?php 
$newargs = array('numberposts'=>'5', 'tag'=>'features', 'category'=>'20');
$featposts = get_posts($newargs);
foreach( $featposts as $post ) : setup_postdata($post);  
$posts_exclude[] = $post->ID; ?>
     <h3><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h3>
          <?php the_excerpt(); ?>
<?php endforeach; ?>

Loop 3 (the paged loop):

Replace:

<?php while ( have_posts() ) : the_post(); ?>

With:

$limit = get_option('posts_per_page');
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
query_posts($query_string.'&showposts=' . $limit . '&paged=' . $paged .'&cat=20');
$wp_query->is_archive = true; $wp_query->is_home = false; ?>
<?php if (have_posts()) : while (have_posts()) : the_post(); if (in_array($post->ID, $posts_exclude)) continue;  ?>

Change cat=20 to your desired category (or remove if using on your index).

Note: We have the paged loop inside of the category template. If you are using for multiple categories, you want to inset the cat id dynamically AND you will need to create a function for posts_exclude so that it is available within the loop file.

Further Steps

On the homepage, the number of posts returned by the paged loop will be less than later pages. On my homepage, 6 posts are excluded. We added a check to see if we are on the homepage, and we increase the limit on the homepage to offset this. We don’t put any posts in the main feature that are more than 10 posts ago, so we do not need to skip posts on later pages. If you have a large number of posts and want to feature posts no longer on the homepage, you will need to increase the limit when a post is excluded.

I will update this post later with a better fix. I have a few projects I’m bouncing back and forth and I just needed a temporary fix until I can go back to that project.

This entry was posted in Wordpress. Bookmark the permalink.

Leave a Reply

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