Two custom loops, pagination, offset

I can’t use only one Loop because of how complicated my markup is.

Markup, no matter how complicated, should never ever be a valid basis when coming to deciding to run multiple loops. Multiple loops should only ever be used if there is absolutely no other means to achieve a certain result, and that is almost always just when different results are needed per query argument, like different posts per page per post type.

Both loops are not restricted by authors or categories or whatever

The above statement also does not validate the use of a second loop. Just based on this statement, we would only need one loop regardless of how complicated your markup is

How the results are displayed from a specific query can always be manipulated by the following

  • rewind_posts() which lets you rerun the loop a second, third or a hundredth time depending on your needs

  • custom counters or the build in loop counter which counts posts and let you do something different if the loop counter/custom counter hits a specific number

  • conditional tags/statements which let target specific posts according to specific conditions, for example post type or category

  • filters like the the_posts which lets you alter the array of returned posts which include adding/removing and/or rearranging posts

  • normal PHP functions like usort() which can be used to sort the returned array of posts before outputting them to screen

  • we can always manipulate the main query with pre_get_posts to display what we want

These are just a few options which you can use instead of running multiple loops. The issue with multiple loops are

  • they are allows problematic when it comes to pagination

  • causes unnecessary database queries which slows page load times and waste resources

One important thing you should always remember is, you must never replace the main loop which displays results from the main query with a custom query. They always lead to more issues than solving them. You should take your time and read the following post:

To solve your issue, you can remove your pre_get_posts action and the found_posts filter as you do not need to set any offsets or recalculate pagination.

You will need to adjust your loop on the desired page according to your needs

EXAMPLE 1

Styling the first post different and display more info that other posts

if ( have_posts() ) {
    while ( have_posts() ) {
        the_post();

            if ( 0 === $wp_query->current_post ) { // Target the first post only
                // Do what you need to do for the first post only
            } else {
                // Display all the other posts as needed   
            }
    }
}

OR

if ( have_posts() ) {
    // Start our custom counter
    $counter = 0;
    while ( have_posts() ) {
        the_post();

            if ( 0 === $counter ) { // Target the first post only
                // Do what you need to do for the first post only
            } else {
                // Display all the other posts as needed   
            }
        // Update the counter 
       $counter++;
    }
}

You can apply this method to any complex markup. You can set custom counters to open and close custom divs, apply different styling to post position or even create post grids. I have done quite a few posts on this, so be sure to search through my answers

EXAMPLE 2

If you need to display posts grouped by post type with post types post and page. Here we will run the loop to display posts from the post post type, rewind the loop and rerun it, but this time display only page post type posts

if ( have_posts() ) {
    while ( have_posts() ) {
        the_post();

            if ( 'post' === get_post_type() ) { // Only display posts from post post type
                // Do what you need to do post post type posts
            } 
    }

    rewind_posts(); // Rewind the loop so we can run it again

    while ( have_posts() ) {
        the_post();

            if ( 'page' === get_post_type() ) { // Only display posts from page post type
                // Do what you need to do page post type posts
            } 
    }
}

CONCLUSION

So as you see, no matter how complex you might feel your mark up is, it always does not validate the need for multiple loops, one loop will always be enough, we just need to use the loop, PHP and filters cleverly to our advantage

Leave a Comment