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' );
}
}