Note that with a custom WP_Query
class instance like the $homePageArticles
in your case, you should pass the max_num_pages
property of the class instance to paginate_links()
:
paginate_links( array(
'total' => $homePageArticles->max_num_pages,
) )
However, that alone will not work with custom offset which breaks the pagination, hence for example you got this issue:
it just shows the same posts on each page
But it can be fixed and it's quite easy:
Calculate the offset based on the current page number and pass the offset to WP_Query
:
// Current page number.
$paged = max( 1, get_query_var( 'paged' ) );
$per_page = 18; // posts per page
$offset_start = 9; // initial offset
$offset = $paged ? ( $paged - 1 ) * $per_page + $offset_start : $offset_start;
$homePageArticles = new WP_Query( array(
'posts_per_page' => $per_page,
'offset' => $offset,
'post_type' => 'articles',
// No need to set 'paged'.
) );
Recalculate the max_num_pages
property and pass it to paginate_links()
:
$homePageArticles->found_posts = max( 0, $homePageArticles->found_posts - $offset_start )
$homePageArticles->max_num_pages = ceil( $homePageArticles->found_posts / $per_page );
while ( $homePageArticles->have_posts() ) ...
echo paginate_links( array(
'current' => $paged,
'total' => $homePageArticles->max_num_pages,
...
) );
But then, if you're making the custom WP query in an archive template, e.g. archive-articles.php
(archive-<post type>
.php)
Then you should just forget that custom WP query.
And instead, use the pre_get_posts
hook to filter the main WP query args (to set the custom offset), then use the found_posts
hook to make sure we have the correct max_num_pages
value, then just loop through the posts in the main query.
In the theme functions file:
function my_pre_get_posts( $query ) {
if ( ! is_admin() && $query->is_main_query() &&
is_post_type_archive( 'articles' )
) {
$query->set( 'offset_start', 9 );
$query->set( 'posts_per_page', 18 );
}
if ( $offset = $query->get( 'offset_start' ) ) {
$per_page = absint( $query->get( 'posts_per_page' ) );
$per_page = $per_page ? $per_page : max( 1, get_option( 'posts_per_page' ) );
$paged = max( 1, get_query_var( 'paged' ) );
$query->set( 'offset', ( $paged - 1 ) * $per_page + $offset );
}
}
add_action( 'pre_get_posts', 'my_pre_get_posts' );
function my_found_posts( $found_posts, $query ) {
if ( $offset = $query->get( 'offset_start' ) ) {
$found_posts = max( 0, $found_posts - $offset );
}
return $found_posts;
}
add_filter( 'found_posts', 'my_found_posts', 10, 2 );
Then in your archive template:
// No need for the "new WP_Query()".
while ( have_posts() ) : the_post();
... your code.
endwhile;
// No need to set 'current' or 'total'.
echo paginate_links( array(
'prev_text' => 'NEWER',
'next_text' => 'OLDER',
...
) );
And actually, with the custom functions in #1 above, you could simply use the custom offset_start
arg with any WP_Query
instances:
// Current page number.
$paged = max( 1, get_query_var( 'paged' ) );
$homePageArticles = new WP_Query( array(
'posts_per_page' => 18,
'offset_start' => 9, // <- set this
'post_type' => 'articles',
// No need to set 'paged' or 'offset'.
) );
while ( $homePageArticles->have_posts() ) ...
echo paginate_links( array(
'current' => $paged,
'total' => $homePageArticles->max_num_pages,
...
) );