Site icon Hip-Hop Website Design and Development

Problem with custom WP_Query and underlying pagination/posts_per_page

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('&laquo;')) {
        printf('<li>%s</li>' . "n", get_previous_posts_link('&laquo;'));
    }

    /** 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('&raquo;', $max)) {
        printf('<li>%s</li>' . "n", get_next_posts_link('&raquo;', $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.