nickpish
nickpish

Reputation: 847

Filter product category archive pages in WooCommerce

I'm currently working on a WordPress/WooCommerce bookstore site, that uses a custom taxonomy.php WooCommerce template to display sets of products by one product category called "Highlights". So, for example, /books/product-category/highlights/best-sellers displays products associated with the "Best Sellers" sub-category of "Highlights". What I'd like to do is add filter functionality to these archive pages to allow more fine-grained views of these product categories by a different category called "Topics". So, for example, checking a box on the "Best Sellers" page for "Art" would show Best Sellers within that category.

Ultimately, I'd like to do so using a $_GET parameter in the URL, such as /books/product-category/highlights/best-sellers/?topic=art. I have been experimenting with pre_get_posts but my results have been a bit erratic at best. Here is what I have tried thus far in functions.php:

add_action('pre_get_posts', 'filter_product_topic');

function filter_product_topic($query) {

    if( is_admin() ) return;
    $tax_query = $query->get('tax_query');

    if( isset($_GET['topic']) ) {
        $tax_query[] = array(
            'taxonomy'       => 'product_cat',
            'field'   => 'slug',
            'terms'     => $_GET['topic'],
            'operator'   => 'IN'
        );
    }
    $query->set('tax_query', $tax_query);
}

As a very basic test, this seems to work for the main archive query, but it seems to have an adverse effect on the rest of the template, and looks to disrupt a different query on the page for a hero element that shows a carousel of different products. For those more familiar with WooCommerce, I'm wondering if there's a better way for me to achieve the desired result and to only impact the main archive product query, and not any others that might exist in the template?

Thanks for any assistance here, and please let me know if my question or related details are unclear in any way.

Upvotes: 3

Views: 5747

Answers (1)

LoicTheAztec
LoicTheAztec

Reputation: 253784

In your code, the main missing thing should be to use is_main_query() WP_Query method this way:

if( ! $query->is_main_query() ) return;

Alternatively instead of using WordPress pre_get_posts filter hook, in Woocommerce for a Tax query you can use dedicated woocommerce_product_query_tax_query filter hook, that already include is_main_query() Wordpress WP_Query method.

This hook is part of woocommerce dedicated WC_Query class. So try this:

add_filter( 'woocommerce_product_query_tax_query', 'filter_product_topic', 10, 2 );
function filter_product_topic( $tax_query, $query ) {
    // Only on Product Category archives pages
    if( is_admin() || ! is_product_category()  ) return $tax_query;

    // The taxonomy for Product Categories
    $taxonomy = 'product_cat';

    if( isset( $_GET['topic'] ) && ! empty( $_GET['topic'] )) {
        $tax_query[] = array(
            'taxonomy'       => $taxonomy,
            'field'   => 'slug',
            'terms'     => array( $_GET['topic'] ),
            'operator'   => 'IN'
        );
    }

    return $tax_query;
}

Code goes in function.php file of your active child theme (or active theme). It should works.

Upvotes: 1

Related Questions