1

I am trying to build search for woocommerce. I am using woocommerce 9.7 and latest wordpress. And the search i want is with multiple taxonomies (categories) so I registered 2 more taxonomies on top of the default product_cat and product_brand so here is the taxonomy code:

function custom_product_filter_taxonomies() {
register_taxonomy('vrsta', 'product', [
    'label' => 'Vrsta',
    'rewrite' => ['slug' => 'vrsta'],
    'hierarchical'      => true,
    'public'            => true,
    'publicly_queryable' => true,
    'show_ui'           => true,
    'show_admin_column' => true,
    'show_in_nav_menus' => true,
    'show_in_rest'      => true,
    'query_var'         => true,
    'show_in_rest'      => true,

]);

register_taxonomy('karakteristike', 'product', [
    'label' => 'Karakteristike',
    'rewrite' => ['slug' => 'karakteristike'],
    'hierarchical'      => true,
    'public'            => true,
    'publicly_queryable' => true,
    'show_ui'           => true,
    'show_admin_column' => true,
    'show_in_nav_menus' => true,
    'show_in_rest'      => true,
    'query_var'         => true,
    'show_in_rest'      => true,
]);

} add_action('init', 'custom_product_filter_taxonomies');

And my search form contains:

input name="s"
input name="product_cat[]"
input name="product_brand[]"
input name="vrsta[]"
input name="kategorija[]"
input name="min_price"
input name="max_price"

And here is the query i am trying to modify:

function woo_custom_filter_products_query($query) {
if (is_admin() || !$query->is_main_query() || !is_post_type_archive('product')) return;

$taxonomies = array('product_cat', 'product_brand', 'vrsta', 'karakteristike');
$filter_args = false;

foreach ($taxonomies as $taxonomy) {
    if (isset($_GET[$taxonomy]) && !empty($_GET[$taxonomy])) {
        //$terms = array_map('intval', array_filter((array) $_GET[$taxonomy]));
        $terms = array_filter($_GET[$taxonomy]);
        if (!empty($terms)) {
            $filter_args[] = array(
                'taxonomy' => $taxonomy,
                'field'    => 'term_id',
                'terms'    => $terms,
                'operator' => 'IN',
            );
        }
    }
}

if(!empty($filter_args)) {
    $taxquery = array_merge(array('relation' => 'OR'), $filter_args);
    //$taxquery = array( 'relation' => 'OR', $filter_args );
    $query->set('tax_query', $taxquery);
}


// Price filtering
if (isset($_GET['min_price']) || isset($_GET['max_price'])) {
    $meta_query = $query->get('meta_query', array());

    if (isset($_GET['min_price']) && is_numeric($_GET['min_price'])) {
        $meta_query[] = array(
            'key'     => '_price',
            'value'   => floatval($_GET['min_price']),
            'compare' => '>=',
            'type'    => 'NUMERIC'
        );
    }

    if (isset($_GET['max_price']) && is_numeric($_GET['max_price'])) {
        $meta_query[] = array(
            'key'     => '_price',
            'value'   => floatval($_GET['max_price']),
            'compare' => '<=',
            'type'    => 'NUMERIC'
        );
    }

    $query->set('meta_query', $meta_query);
}
}
add_action('pre_get_posts', 'woo_custom_filter_products_query');

The problem I am running into is if I use OR in tax_query then it works if i select vrsta category and it shows every product from that category, for example vrsta food it shows all product selected with food BUT it also shows all products from other selected categories.

So selecting vrsta food and procuct_brand Good brand it will show me all products from good brand and also all products from food which means it will show me products from other brands too.

I was thinking that using relation AND will solve this and it will show only what was selected in vrsta AND product_brand however in this case it shows me There are no products at all moreover, if i select only vrsta food it is supposed only to show food products and not drinks products but it shows like taxonomy doesn't even exist so like it doesn't work at all.

3
  • The problem lies in how the tax_query array is being structured Commented Aug 4 at 1:42
  • If you want vrsta to only return products that match both conditions, then you should split each term into its own subquery. This way AND applies across different taxonomies, and each term is treated individually. See these related questions: WP_Query Woocommerce products that belong in distinct multiple categories only tax_query and Tax query using AND relation for 2 category terms in WooCommerce. Commented Aug 5 at 12:02
  • relation by default is AND so no need to define it unless you will use OR. Check if you always get arrays or just update $terms = array_filter((array) $_GET[$taxonomy]); . Also either update to use AND in $taxquery = array_merge(array('relation' => 'OR'), $filter_args); or simply $taxquery = $filter_args; Commented Aug 7 at 12:37

2 Answers 2

1

So I found the solution. The problem was all this time because I was using ID for the filters, and just using slug instead of id it works, so in input fields values should be slug not the id and query filter works correctly.

foreach ($taxonomies as $taxonomy) {
    if (isset($_GET[$taxonomy]) && !empty($_GET[$taxonomy])) {
        //$terms = array_map('intval', array_filter((array) $_GET[$taxonomy]));
        $terms = array_filter($_GET[$taxonomy]);
        if (!empty($terms)) {
            $filter_args[] = array(
                'taxonomy' => $taxonomy,
                'field'    => 'slug',
                'terms'    => $terms,
                'operator' => 'IN',
            );
        }
    }
}
Sign up to request clarification or add additional context in comments.

Comments

0

This is the basics of using 'AND' & 'OR':

  1. Use 'AND' if you want products that match all selected taxonomies.

  2. Use 'OR' if you want products matching any of the taxonomies (less strict).

  3. Your original issue where 'AND' shows no results is likely because no products have terms matching all selected taxonomies simultaneously.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.