1

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:

$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.

2

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.

  • It's important also the post_type and tax_query or this is a cover only for the posts_per_page parameter? The post_type and tax_query can be specified also this way or just the pagination part? – Grávuj Miklós Henrich Sep 30 '13 at 13:53
  • designloud.com/how-to-add-products-per-page-dropdown-to-woocommerce/ this dropdown was used by me. – Grávuj Miklós Henrich Sep 30 '13 at 14:13
  • @GrávujMiklósHenrich ...and why didn't you add that to your initial question? sigh .. but nvm, it's not different from what I added to the answer. – kaiser Sep 30 '13 at 14:43
  • Sorry. I was interested only on the pagination issue, but if all query must be solved by using the pre_get_posts, then I need to specify the tax_query parameter is important and the second arrays term is different from page to page. So I'm not sure if your solution will work with WooCommerce. Also if you take a look on the example link pasted above, you'll see that WooCommerce can be hooked with filters, actions, etc. – Grávuj Miklós Henrich Sep 30 '13 at 14:50
  • Just pass everything you need to pre_get_posts - your tax_query as well. Look through the archives here on the page. No need to use plugin specific filters anywhere here. Core filters should always be used first. Plugin filters are just there in case core doesn't provide what one needs. – kaiser Sep 30 '13 at 14:51
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.

  • 1
    You could take advantage of your solution and simply use the pre_get_posts filter so you save this additional query and instead modify the main one. – kaiser Sep 30 '13 at 12:37
  • Hi. Thank you for taking the time and answering my question. By main query you mean the default woocommerce product query? Because in my example I have only one query. – Grávuj Miklós Henrich Sep 30 '13 at 13:11
  • 1
    By main query I mean the main query from WordPress. Whatever WooCommerce does in the background, there's always one main query that happens on every request. Additional queries are meant for additional loops. When you add a new template (or alter an existing one) then your loop will display the data from the main query no matter what. What you're currently doing is simply adding an additional one saved into $wp_query - btw, poor naming choice as it's the name of the global. The other one to avoid is $wp_the_query. – kaiser Sep 30 '13 at 13:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.