WooCommerce – results per page not working after page reload

What I wanted to achieve is to list some products on a custom page which belongs to two common categories. This part is working fine, except the results per page dropdown. When I change the dropdown values to 24/36/48, after page reload the number of products shown is the same as on the initial pageload.

I have the following code:

Read More
$wp_query = new WP_Query(
    array(
        'post_type' => 'product',
        'tax_query' => array(
            'relation' => 'AND',
                array(
                    'taxonomy'  => 'product_cat',
                    'field'     => 'slug',
                    'terms'     => 'new-arrivals'
                ),
                array(
                    'taxonomy'  => 'product_cat',
                    'field'     => 'slug',
                    'terms'     => 'earrings'
                )
            )
    )
);
while ( $wp_query->have_posts() ) : $wp_query->the_post();
woocommerce_get_template( 'archive-product.php' );
endwhile;
wp_reset_postdata();
wp_link_pages(array('before' => '<p><strong>Pages:</strong> ', 'after' => '</p>', 'next_or_number' => 'number'));

I would like to get some directions on how to customise the loop to meet also the results per page functionality. I know I am missing sending and getting the dropdown values, but have no clue (yet) on how to do it with best practice, without cruel PHP and JS. There must be some WooCommerce styled best practice. If my code can be customised or if I’m on a totally wrong way. If so, where I made the mistake?

I thought this was will be the simple one, did not payed attention to the “posts per page” detail.

Related posts

2 comments

  1. Let’s imagine you got a dropdown like the following

    // The template tag that you place in your ... template
    function WPSE116198PerPageSelect()
    {
        $selected = 
        <?php
        <select name="woo_per_page" id="woo_per_page" size="3">
            <?php
            foreach ( array( 24, 36, 48 ) as $val )
            {
                ?><option <?php value="<?php echo $val; ?> selected( get_query_var( 'woo_per_page' ), $val ); ?>>
                    <?php echo $val; ?>
                </option><?php
            }
            ?>
        </select>
        ?>
    }
    

    Then we need a callback for pre_get_posts:

    add_action( 'pre_get_posts', 'WPSE116198PerPageCb' );
    function WPSE116198PerPageCb( $query )
    {
        if (
            isset( $_POST['woo_per_page'] )
            AND in_array( absint( $_POST['woo_per_page'] ) ), array( 24, 36, 48 ) )
            )
        {
            $per_page = absint( esc_attr( $_POST['woo_per_page'] ) );
            $query->set( 'posts_per_page', $per_page );
        }
    
        return $query;
    }
    

    This code isn’t tested, I’m no WooCommerce expert and you’ll probably as well consider the offset, the numposts and paged/page for pagination.

  2. Temporarily “cruel” PHP workout:

    if ( $_POST['woocommerce-sort-by-columns'] ) {
        $wsbc = $_POST['woocommerce-sort-by-columns'];
    } else {
        $wsbc = '9';
    }
    $wp_query = new WP_Query(
        array(
            'post_type' => 'product',
            'tax_query' => array(
                'relation' => 'AND',
                    array(
                        'taxonomy'  => 'product_cat',
                        'field'     => 'slug',
                        'terms'     => 'new-arrivals'
                    ),
                    array(
                        'taxonomy'  => 'product_cat',
                        'field'     => 'slug',
                        'terms'     => 'rings'
                    )
                ),
            'posts_per_page' => $wsbc
        )
    );
    while ( $wp_query->have_posts() ) : $wp_query->the_post();
    woocommerce_get_template( 'archive-product.php' );
    endwhile;
    wp_reset_postdata();
    wp_link_pages(array('before' => '<p><strong>Pages:</strong> ', 'after' => '</p>', 'next_or_number' => 'number'));
    

    But I’m almost sure there must be a best practice solution.

Comments are closed.