understrap / understrap-child

The starter child theme for Understrap, the renowned open-source WordPress starter theme.
GNU General Public License v3.0
580 stars 330 forks source link

Custom query members category - understrap_pagination not working #387

Closed currentcreative closed 7 months ago

currentcreative commented 8 months ago

Can anyone spot what's wrong with this code?

I added a $paged variable to the custom query and I put 'total' => $catquery->max_num_pages in the understrap_pagination function as per the suggestions in this StackExchange thread.

This is in my members-category.php template, which is just a modification of the original category.php template:

  <main class="site-main" id="main">

    <?php
            // Get the current page number for pagination
            $paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;

            // Custom query to get posts of the "Members" category sorted alphabetically
            $args = array(
                'post_type'      => 'post', // You can change this to your custom post type if needed
                'posts_per_page' => 5,
                'category_name'  => 'members', // Replace with your actual category slug
                'orderby'        => 'title',
                'order'          => 'ASC',
                'paged'          => $paged, // Handle pagination
            );

            $catquery = new WP_Query( $args );

            if ( $catquery->have_posts() ) {
                ?>
    <header class="page-header">
      <?php
                    the_archive_title( '<h1 class="page-title">', '</h1>' );
                    the_archive_description( '<div class="taxonomy-description">', '</div>' );
                    ?>
    </header><!-- .page-header -->
    <?php
                // Start the loop.
                while ( $catquery->have_posts() ) {
                    $catquery->the_post();

                    /*
                     * Include the Post-Format-specific template for the content.
                     * If you want to override this in a child theme, then include a file
                     * called content-___.php (where ___ is the Post Format name) and that will be used instead.
                     */
                    get_template_part( 'loop-templates/content', get_post_format() );
                }

                // Display pagination
                understrap_pagination( [
                                        'total' => $catquery->max_num_pages
                                    ] );

                // Restore original post data.
                wp_reset_postdata();
            } else {
                get_template_part( 'loop-templates/content', 'none' );
            }
            ?>

  </main>

  <?php
        // Do the right sidebar check and close div#primary.
        get_template_part( 'global-templates/right-sidebar-check' );
        ?>

</div><!-- .row -->

<?php get_footer();

jholmes-dev commented 7 months ago

Could you expand on what exactly is happening, and how it's not working? What error it's throwing, unexpected result, etc.?

currentcreative commented 7 months ago

The pagination simply doesn't work. I press the 2 for page 2 and it takes me to a page that says "Oops! That page can’t be found." The first page shows up, but the pagination doesn't work even though the url says "category/members/page/2/" as it should.

There is no documentation about the Understrap pagination function, is there?

jholmes-dev commented 7 months ago

This is actually due to how WordPress handles pagination. WordPress generates pagination permalinks before reading your theme's template files, and the default value it uses for pagination is whatever is set for Blog pages to show at most under Settings->Reading.

This causes problems when you set the posts_per_page argument lower than the Blog pages to show at most setting within a custom loop within a template, as the pages required are higher than the pages generated.

There are a couple ways to fix this, the easiest would be to update Blog pages to show at most to whatever value you want posts_per_page to be. The potential downside here is that this will be applied site-wide.

The second option is to update the posts_per_page argument in your theme's functions.php file using the pre_get_posts hook. This way you can check the passed query for a specific category:

function change_posts_per_page( $query ) {
   if ( $query->is_category( 'members' ) )
      $query->set( 'posts_per_page', 5 );
}
add_action( 'pre_get_posts', 'change_posts_per_page' );

Related: https://core.trac.wordpress.org/ticket/11067

currentcreative commented 7 months ago

Thank you! As to the functions.php suggestion, I did eventually move all the custom query logic into functions.php later and got it working that way, but I thought I would rather have all the custom query logic in the template so it's nice and neat. Turns out I was wrong about that.

Now, I realize putting it in functions.php is better because then I don't have to affect Reading settings for the whole entire site, which is something that hadn't really occurred to me when I was just trying to get this set up. They don't have any other blog section and most sites I work on don't, so this issue hasn't really come up before (especially since I usually am just using Wordpress's default pagination rather than Understrap's custom pagination function).

Adjusting Settings -> Reading was actually the first thing I did, but somewhere along the way of trying to figure out why my code wasn't working, I ended up with the default Reading settings of 10 instead of 5....I just tried setting the Reading to 5 again and the code above actually works! Hooray!

However, I'm putting all custom query logic into functions.php from now on, now that I truly understand how Reading works. A good learning experience. Thank you for helping me figure this out.