我遇到了WooCommerce的问题,并且使用Layered Nav小部件一次按多个属性进行过滤。我知道有一些其他的插件提供ajax过滤,但是他们的文档似乎并没有暗示他们会解决这个问题,并且WC文档在这个问题上没有提供任何内容。我不知道我是否遗漏了一些明显的东西,因为我想每个使用过滤器的网站都希望它们以我在下面概述的方式工作,而不是它们当前的工作。
我的网站使用三个属性: - 颜色 - 服装类型 - 品牌
我在侧边栏中设置了3个Layered Nav小部件实例,以便客户找到他们想要的内容。对于所有3我使用查询类型“OR”,以便如果客户启用蓝色和绿色和红色过滤器选项,他们可以看到任何产品是蓝色或绿色或红色。同样适用于品牌和服装类型。
我遇到的问题是这些小部件似乎没有选择在属性之间指定AND或OR。当我在网站上使用服装过滤器时,我会期望以下逻辑:
颜色:绿色或蓝色 和 品牌:耐克或阿迪达斯 和 类型:配件或上衣或下装
但是所有东西都只是一个长的OR查询所以一件衣服可能是蓝色的或者是一个配件或者nike OR green或adidas。
结果是,即使品牌过滤器只需要耐克或阿迪达斯,客户也会获得许多他们不想看到的产品,即Puma产品会出现,因为它是蓝色的。
有没有办法将查询链接在一起,以便WITHIN属性我们使用OR,但是我们使用AND属性?我想这个SQL查询不会太复杂,我只是希望有一个扩展来为我处理这个问题。
提前致谢!
答案 0 :(得分:0)
/woocommerce/includes/cass-wc-query.php 729行。 像这样更改功能layered_nav_query:
/**
* Layered Nav post filter.
*
* @param array $filtered_posts
* @return array
*/
public function layered_nav_query( $filtered_posts ) {
global $_chosen_attributes;
if ( sizeof( $_chosen_attributes ) > 0 ) {
foreach ( $_chosen_attributes as $attribute => $data ) {
$matched_products_from_attribute = array();
$filtered = false;
if ( sizeof( $data['terms'] ) > 0 ) {
foreach ( $data['terms'] as $value ) {
$args = array(
'post_type' => 'product',
'numberposts' => -1,
'post_status' => 'publish',
'fields' => 'ids',
'no_found_rows' => true,
'tax_query' => array(
array(
'taxonomy' => $attribute,
'terms' => $value,
'field' => 'term_id'
)
)
);
$post_ids = apply_filters( 'woocommerce_layered_nav_query_post_ids', get_posts( $args ), $args, $attribute, $value );
if ( ! is_wp_error( $post_ids ) ) {
if ( sizeof( $matched_products_from_attribute ) > 0 || $filtered ) {
$matched_products_from_attribute = $data['query_type'] == 'or' ? array_merge( $post_ids, $matched_products_from_attribute ) : array_intersect( $post_ids, $matched_products_from_attribute );
} else {
$matched_products_from_attribute = $post_ids;
}
$filtered = true;
}
}
}
$results = isset($results)
? array_intersect($results, $matched_products_from_attribute)
: $matched_products_from_attribute;
$this->filtered_product_ids_for_taxonomy[ $attribute ] = $matched_products_from_attribute;
}
if ( $filtered ) {
WC()->query->layered_nav_post__in = $results;
WC()->query->layered_nav_post__in[] = 0;
if ( sizeof( $filtered_posts ) == 0 ) {
$filtered_posts = $results;
$filtered_posts[] = 0;
} else {
$filtered_posts = array_intersect( $filtered_posts, $results );
$filtered_posts[] = 0;
}
}
}
return (array) $filtered_posts;
}