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.
vrstato only return products that match both conditions, then you should split each term into its own subquery. This wayANDapplies 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.$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;