Wordpress - WP_Query Pagination on single-custom.php
You have 2 problems.
First problem
The line
$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
will fail, because on singular post view, when the URL contains '/page/XX/'
, the variable WordPress sets is 'page'
and not 'paged'
.
You may think to use 'page'
instead of 'paged'
, but that will not work either, because once the 'page'
variable is intended to be used for multi-page singular post (page separation using <!--nextpage-->
) and once the post is not multi-page, WordPress will redirect the request to the URL without '/page/XX/'
.
This is what happens when you name your query variable $wp_query
.
The solution is to prevent that redirection by removing the function responsible for it, which is 'redirect_canonical'
hooked into 'template_redirect'
:
So, in your functions.php
add:
add_action( 'template_redirect', function() {
if ( is_singular( 'authors' ) ) {
global $wp_query;
$page = ( int ) $wp_query->get( 'page' );
if ( $page > 1 ) {
// convert 'page' to 'paged'
$wp_query->set( 'page', 1 );
$wp_query->set( 'paged', $page );
}
// prevent redirect
remove_action( 'template_redirect', 'redirect_canonical' );
}
}, 0 ); // on priority 0 to remove 'redirect_canonical' added with priority 10
Now WordPress will not redirect anymore and will set correctly the 'paged'
query var.
Second problem
next_posts_link()
and previous_posts_link()
both check if ( ! is_single() )
to display pagination.
Now, is_single()
is true in your case, because you are in a single post of 'author' type, so those functions can't work as you expect.
You have 3 possibilities:
- Use
query_posts
to override the main query (really not recommended) - Use a custom page template instead of a custom post type, because
is_single()
is false for pages, and your code will work there. - Write your own pagination function and use that
That's the code for solution number #3:
function my_pagination_link( $label = NULL, $dir = 'next', WP_Query $query = NULL ) {
if ( is_null( $query ) ) {
$query = $GLOBALS['wp_query'];
}
$max_page = ( int ) $query->max_num_pages;
// only one page for the query, do nothing
if ( $max_page <= 1 ) {
return;
}
$paged = ( int ) $query->get( 'paged' );
if ( empty( $paged ) ) {
$paged = 1;
}
$target_page = $dir === 'next' ? $paged + 1 : $paged - 1;
// if 1st page requiring previous or last page requiring next, do nothing
if ( $target_page < 1 || $target_page > $max_page ) {
return;
}
if ( null === $label ) {
$label = __( 'Next Page »' );
}
$label = preg_replace( '/&([^#])(?![a-z]{1,8};)/i', '&$1', $label );
printf( '<a href="%s">%s</a>', get_pagenum_link( $target_page ), esc_html( $label ) );
}
and use it like so in the single-authors.php
:
my_pagination_link( 'Older Entries', 'next', $author_query );
my_pagination_link( 'Newer Entries', 'prev', $author_query );