In my category template (category.php) I have the following code:
<?php
// Setup custom loop -- we need to exclude featured posts from listing so they aren't repeated
$paged = get_query_var('paged') ? absint(get_query_var( 'paged' )) : 1;
$args = [
'post_type' => 'post',
'cat'=> $current_category->cat_ID,
'post_status' => 'publish',
'paged' => $paged,
'posts_per_page' => $posts_per_page,
'orderby' => 'date',
'order' => 'DESC'
];
// If we have posts to exclude -- add that argument
if (!empty($featured_posts_to_exclude)) {
$args['post__not_in'] = $featured_posts_to_exclude;
}
$category_posts = new WP_Query($args);
if ( $category_posts->have_posts() ) :
// Used in template part to vary content
$loop_count = 0;
/* Start the Loop */
while ( $category_posts->have_posts() ) : $category_posts->the_post();
// We use this instead of "get_template_parts" so that we can pass loop vars
include(locate_template('template-parts/content-horz-ads.php', false, false));
$loop_count++;
endwhile;
// Add pagination
im_numeric_posts_nav($category_posts);
// Reset since we are using a custom loop.
wp_reset_postdata();
else :
get_template_part( 'template-parts/content', 'none' );
endif;
My pagination function is as follows (I’m posting it for the sake of completeness, but it works absolutely fine whether posts_per_page is set to 10, or 6 or whether it’s a custom loop or not — it displays the correct links, and number of links):
function im_numeric_posts_nav($custom_query_object = null) {
// If we're on a singular page, we don't need navigation
if (is_singular()) {
return;
}
// If a custom loop was passed in, use it...otherwise use global loop
if ($custom_query_object !== null) {
$wp_query = $custom_query_object;
} else {
global $wp_query;
}
/** Stop execution if there's only 1 page */
if ($wp_query->max_num_pages <= 1) {
return;
}
$paged = get_query_var('paged') ? absint(get_query_var( 'paged' )) : 1;
$max = intval($wp_query->max_num_pages);
/** Add current page to the array */
if ($paged >= 1) {
$links[] = $paged;
}
/** Add the pages around the current page to the array */
if ($paged >= 3) {
$links[] = $paged - 1;
$links[] = $paged - 2;
}
if (($paged + 2) <= $max) {
$links[] = $paged + 2;
$links[] = $paged + 1;
}
echo '<div class="pagination"><ul>' . "n";
/** Previous Post Link */
if (get_previous_posts_link('«')) {
printf('<li>%s</li>' . "n", get_previous_posts_link('«'));
}
/** Link to first page, plus ellipses if necessary */
if (!in_array( 1, $links)) {
$class = 1 == $paged ? ' class="active"' : '';
printf('<li%s><a href="%s">%s</a></li>' . "n", $class, esc_url(get_pagenum_link(1)), '1');
if (!in_array(2, $links)) {
echo '<li>…</li>';
}
}
/** Link to current page, plus 2 pages in either direction if necessary */
sort($links);
foreach ((array) $links as $link) {
$class = $paged == $link ? ' class="active"' : '';
printf('<li%s><a href="%s">%s</a></li>' . "n", $class, esc_url(get_pagenum_link($link )), $link);
}
/** Link to last page, plus ellipses if necessary */
if (!in_array($max, $links)) {
if (!in_array($max - 1, $links)) {
echo '<li>…</li>' . "n";
}
$class = $paged == $max ? ' class="active"' : '';
printf('<li%s><a href="%s">%s</a></li>' . "n", $class, esc_url(get_pagenum_link($max)), $max);
}
/** Next Post Link */
if (get_next_posts_link('»', $max)) {
printf('<li>%s</li>' . "n", get_next_posts_link('»', $max));
}
echo '</ul></div>' . "n";
}
On category pages with featured posts, $posts_per_page
is set to 6.
It shows only 6 posts but the pagination query still thinks there is 10 posts per page.
There are 214 posts but there should be 35 pages only, but if I go to any page after page 22, I get a 404. Which tells me that it’s still using the posts per page
that is set in the WordPress admin under the Reading settings
.
If I change that to “6” — everything is perfectly rosey. However i don’t want that default set to 6. I want to be able to set that via the posts_per_page
var in the custom query.
Any idea why this is happening, or what I have wrong here? I’m really banging my head on this.