You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从自定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 23:53:23