如何从自定义WP_Query的WooCommerce商品中提取属性及数量用于筛选?
从WP_Query结果中提取WooCommerce商品属性及对应数量
问题场景
在自定义页面中,通过WP_Query获取了分类ID为41的WooCommerce商品,代码如下:
$query = new WP_Query($args = array( 'post_type' => 'product', 'post_status' => 'publish', 'ignore_sticky_posts' => 1, 'posts_per_page' => -1, 'tax_query' => array( array( 'taxonomy' => 'product_cat', 'terms' => 41, ), ), )); ?> <div class="products"> <?php if ($query->have_posts()) : while ($query->have_posts()) : $query->the_post(); wc_get_template_part('content', 'product-list'); endwhile; wp_reset_postdata(); endif; ?> </div>
需要从上述查询结果的商品中提取指定属性(如pa_size、pa_color)及其对应的商品数量,用于生成单选/复选框筛选控件。当前使用get_terms("pa_size")会返回该属性的所有选项,而非当前查询商品中存在的属性;且WooCommerce自带筛选器在自定义页面无法生效。
解决方案
方法1:遍历WP_Query结果收集属性(适合商品数量较少的场景)
遍历查询到的每个商品,提取对应属性的术语,再统计每个术语出现的次数:
// 定义需要提取的属性 taxonomy $target_attributes = array('pa_size', 'pa_color'); // 存储属性及对应数量的数组 $attribute_counts = array(); // 初始化统计数组 foreach ($target_attributes as $tax) { $attribute_counts[$tax] = array(); } if ($query->have_posts()) : // 遍历所有商品 while ($query->have_posts()) : $query->the_post(); $product = wc_get_product(get_the_ID()); foreach ($target_attributes as $tax) { // 获取当前商品的该属性术语 $terms = $product->get_attribute($tax); if (!empty($terms)) { // 处理多值属性(用逗号分隔的情况) $term_names = explode(', ', $terms); foreach ($term_names as $name) { // 通过术语名称获取术语对象,确保ID一致 $term = get_term_by('name', $name, $tax); if ($term && !is_wp_error($term)) { $term_id = $term->term_id; // 统计数量 if (isset($attribute_counts[$tax][$term_id])) { $attribute_counts[$tax][$term_id]['count']++; } else { $attribute_counts[$tax][$term_id] = array( 'name' => $term->name, 'slug' => $term->slug, 'count' => 1 ); } } } } } endwhile; wp_reset_postdata(); endif; // 输出属性筛选控件(示例:复选框) foreach ($attribute_counts as $tax => $terms) { if (!empty($terms)) { echo '<div class="filter-group">'; echo '<h3>' . wc_attribute_label($tax) . '</h3>'; foreach ($terms as $term_id => $data) { echo '<label><input type="checkbox" name="' . $tax . '[]" value="' . $data['slug'] . '"> ' . $data['name'] . ' (' . $data['count'] . ')</label>'; } echo '</div>'; } }
方法2:自定义SQL查询(适合商品数量较多的场景,效率更高)
直接通过SQL查询,根据WP_Query返回的商品ID集合,获取对应属性的术语及数量:
// 获取WP_Query结果中的所有商品ID $product_ids = wp_list_pluck($query->posts, 'ID'); if (empty($product_ids)) { return; } $target_attributes = array('pa_size', 'pa_color'); $attribute_counts = array(); global $wpdb; foreach ($target_attributes as $tax) { // 构建SQL查询 $sql = $wpdb->prepare(" SELECT t.term_id, t.name, t.slug, COUNT(tr.object_id) as count FROM {$wpdb->terms} t JOIN {$wpdb->term_taxonomy} tt ON t.term_id = tt.term_id JOIN {$wpdb->term_relationships} tr ON tt.term_taxonomy_id = tr.term_taxonomy_id WHERE tt.taxonomy = %s AND tr.object_id IN (" . implode(',', array_map('intval', $product_ids)) . ") GROUP BY t.term_id ORDER BY t.name ASC ", $tax); $results = $wpdb->get_results($sql); if (!empty($results)) { $attribute_counts[$tax] = $results; } } // 输出属性筛选控件(示例:单选框) foreach ($attribute_counts as $tax => $terms) { echo '<div class="filter-group">'; echo '<h3>' . wc_attribute_label($tax) . '</h3>'; foreach ($terms as $term) { echo '<label><input type="radio" name="' . $tax . '" value="' . $term->slug . '"> ' . $term->name . ' (' . $term->count . ')</label>'; } echo '</div>'; }
内容的提问来源于stack exchange,提问作者Dias
相关产品推荐
相关产品推荐

