Numbered Pagination Showing The Same Posts After Altering WP_Query

After few checking and testing, I figured the problem source and solved it myself, I’ll share it here so anyone in future fall in the same problem, this can surely help.

As I mentioned above the problem wasn’t from the pagination at all, well the pagination got broken yes, but the thing that broke it is the WP_Query parameter offset because it overridden the paged parameter which is an important parameter for pagination.

After few testings I figured how to make a clean and secured pagination after altering the WP_Query, and this is how it should be done, I’ll showcase it below with a clean code and explanation.

function theme_pagination() {

    global $wp_query;
    $totalPages = $wp_query->max_num_pages ;
    $currentPage = max( 1, get_query_var( 'paged' ) );

    if ( $totalPages > 1 ) {

    $big = '9999999';
    return paginate_links( array(
        'format'        => 'page/%#%',
        'base'          => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ))),
        'current'       => $currentPage,
        'total'         => $totalPages,
        'prev_text'     => __( 'Prev', 'domain' ),
        'next_text'     => __( 'Next', 'domain' )
        ) );
    }
}

I think you must be familiar with almost every parameter and function above in the function except the function given in the parameter base, which is mandatory for the pagination to work properly with the search page to not display the same posts in every page.

str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) );

As you know, my plan is to have a featured post in a separated query, and then make another second query to display the rest of posts without duplicating the featured post.

When I first tried to make it work with the offset parameter, It actually worked but it didn’t agree to let the paged parameter work aswell, so I looked and thought of every method to make it work without the offset param, and here is how it worked without any problem.

This is the structure for the first query that displays the Featured Post :

$featured_args = array( 'posts_per_page'    => 1 );
$featured_loop = new WP_Query( $featured_args );

if ( $featured_loop->have_posts() ):
    while ( $featured_loop->have_posts() ): $featured_loop->the_post();
        $do_not_duplicate = $post->ID;

        <article class="featured_post">
            The body of the article goes here...
        </article>
    endwhile; 
    wp_reset_postdata();
endif; ?>

Take a focus look on the variable $do_not_duplicate, I used it to store the Featured Post’s ID in it, to use it later in the second query as below:

Note: If you want to store two posts (jump two posts in the next query), make sure to use it in an array like this:

$do_not_duplicate[] = $post->ID

Here’s how it looks the second query, the part where we do the whole work :

if ( have_posts() ): 
    while ( have_posts() ): the_post();
        if ( $post->ID == $do_not_duplicate ) continue; ?>
            <div class="blog_loop_container">
                <article class="blog_post">
                    The body of the articles goes here...
                </article>
            </div>
    <?php endwhile; ?>
    <div class="pagination_container">
        <?php echo theme_pagination(); ?>
    </div>
<?php endif; ?>

In the second query as you see, don’t alter it, just use your basic query, just remember inside and before printing any article body, make sure to check if there’s duplicated post’s ID to skip it and move on like this :

if ( $post->ID == $do_not_duplicate ) continue; ?>

The variable I stored in the first Post’s ID remember? I used it to check for any duplicated post to skip.

This was my approach to fix the entire pagination in the theme, in archives, search, pages, blog, and everypart of the theme, I hope it helps you, and if there’s any problem, let me know below in a comment so I can help.