Getting pagination for second loop to work on single.php

I am trying to get a basic post pagination to work on the single post page. The code I have used displays 3 posts with the page numbers and next arrow as expected but, clicking this does not show the second page of pagination.

This does work however if Permalinks are set to default?

<?php 
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$args = array('posts_per_page' => 3, 'paged' => $paged, 'page' => $paged );
query_posts($args); ?>

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

….

<?php endwhile; ?>

<nav id="nav-posts">
    <?php the_posts_pagination(); ?>
</nav>

<?php endif; ?>

Any ideas?

1 Answer
1

Here’s a working example of a secondary loop with pagination that can be used on singular posts. WP_Query is typically a better way to go than query_posts(). Your permalink settings shouldn’t be a factor here.

<?php 
    $my_query = new WP_Query( [
        'posts_per_page' => 3,
        'paged' => ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1,
        'post_type' => 'post',
    ] );
?>
<?php if ( $my_query->have_posts() ) : while ( $my_query->have_posts() ) : $my_query->the_post(); ?>
    <h1><?php the_title(); ?></h1>
<?php endwhile; ?>
    <nav id="nav-posts">
        <?php 
            $big = 999999999; // need an unlikely integer
            echo paginate_links( [
                'base'    => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
                'format'  => '?paged=%#%',
                'current' => max( 1, get_query_var('paged') ),
                'total'   => $my_query->max_num_pages,
                'before_page_number' => sprintf( '<span class="screen-reader-text">%1$s</span>', __( 'Page', 'mytextdomain' ) )
            ] );
        ?>
    </nav>
<?php endif; ?>
<?php wp_reset_postdata(); ?>

Getting pagination to work with a second loop on a singular post is a bit tricky. gmazzap posted a comprehensive explanation and solution here. The code below was copied from that solution and is necessary to allow pagination to work with the secondary loop posted above.

    add_action( 'template_redirect', 'wpse247933_single_post_second_loop_pagingation_fix', 0 );
    // on priority 0 to remove 'redirect_canonical' added with priority 10
    function wpse247933_single_post_second_loop_pagingation_fix() {
        if ( is_singular( 'post' ) ) {
            global $wp_query;
            $page = ( int ) $wp_query->get( 'page' );
            if ( $page > 1 ) {
                    // convert 'page' to 'paged'
                    $query->set( 'page', 1 );
                    $query->set( 'paged', $page );
            }
            // prevent redirect
            remove_action( 'template_redirect', 'redirect_canonical' );
        }
    }

Leave a Comment