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