我在 WooCommerce 和使用分层导航小部件一次按多个属性进行过滤时遇到问题。我知道还有一些其他插件提供 ajax 过滤,但它们的文档似乎并没有表明它们会解决这个问题,并且 WC 文档没有提供任何关于这个问题的信息。我不知道我是否在这里遗漏了一些明显的东西,因为我想每个使用过滤器的网站都希望它们按照我在下面概述的方式工作,而不是像现在那样工作。
我的网站使用三个属性: - 颜色 - 服装类型 - 品牌
我在侧边栏中设置了 3 个分层导航小部件实例,以允许客户找到他们想要的内容。对于所有 3 个,我使用“OR”查询类型,这样如果客户启用蓝色、绿色和红色过滤器选项,他们就可以看到任何蓝色或绿色或红色的产品。品牌和服装类型也是如此。
我遇到的问题是这些小部件似乎没有选项来指定属性之间的 AND 或 OR。当我在网站上使用服装过滤器时,我预计会出现以下逻辑:
颜色:绿色或蓝色 和 品牌: 耐克或阿迪达斯 和 类型:配饰 OR 上衣 OR 下装
但一切都只是一个长 OR 查询,因此一件衣服可以是蓝色或配件或耐克或绿色或阿迪达斯。
结果是,顾客会得到很多他们不想看到的产品,即 Puma 产品因为是蓝色而出现,即使品牌过滤器只想要 Nike 或 Adidas。
有没有办法将查询链接在一起,以便在属性内我们使用 OR,但在属性之间我们使用 AND?我想这个 SQL 查询不会太复杂,我只是希望有一个扩展可以帮我处理这个问题。
提前致谢!
/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;
}