category/category_name pagination 404 error

In the template used for category archives you should have no use for new WP_Query. For all the main templates that WordPress loads itself for post archives, WordPress has already queried the correct posts, so you don’t need to query them again with WP_Query. For these templates, it’s the template’s job just to display those posts that have already been queried. This is done using The Loop.

The reason pagination issues are so common with using WP_Query like this is that by default paginate_links() is designed to output pagination links based on the number of posts and posts per page in the ‘main query’ (the query that WordPress has already performed, and that The Loop will output). So if you’re trying to use it with a custom query, and haven’t set it up completely perfectly, then the mismatch between your custom query and the main query will give you broken results.

Even if you might be able to fix the pagination to work with your query, you still have a problem with performing an additional query, which will slow down the site, as well as a bunch of redundant logic. The best solution is to implement the template the way WordPress wants you to.

So based on the markup in your your question, all your template should be is:

<div class="row">
    <?php while ( have_posts() ) : the_post(); ?>
        <div class="col-md-4 module">
            <a href="https://wordpress.stackexchange.com/questions/357331/<?php the_permalink(); ?>">
                <!-- ... -->
            </a>
        </div>
    <?php endwhile; ?>

    <div class="d-flex justify-content-center pagination">
        <?php
        echo paginate_links(
            array(
                'prev_text' => '<<',
                'next_text' => '>>',
            )
        );
        ?>
    </div>
</div>

This will output the posts in the current category using your markup, with your pagination controls.

So what if you want to change something about the posts that were queried, such as the order, or number of posts per page? If you search for “query number of posts per page” or “order posts in reverse” you might see a lot of examples using new WP_Query. These answers are demonstrating how to set those properties for a new query, not the existing main query. The process for changing these properties for the main query is a little different.

To change the number of posts or order of the main query, rather than putting this in the template, you need to add a function to your themes functions.php that is hooked into pre_get_posts. This function will give you an opportunity to change the properties of the main query. For example, if you want to change the number of posts per page for category archives, you would add the following:

add_action(
    'pre_get_posts',
    function( $query ) {
        // We don't want to affect any back-end queries.
        if ( is_admin() ) {
            return;
        }

        // We only want to modify the main query for category archives.
        if ( $query->is_category() ) {
            // Change the number of posts per page.
            $query->set( 'posts_per_page', 3 );
        }
    }
);

That will change category pages to only display 3 posts per page, but the pagination will continue to work because you’ve modified the main query that the pagination controls are for.

You’ll find a lot more resources on this method of modifying queries by googling “pre_get_posts”.

Leave a Comment