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

WooCommerce产品对比表如何自动获取全部产品属性

解决WooCommerce产品对比表自动获取所有产品属性的问题

我正在开发WooCommerce产品对比表,目前已实现thumbnail、name、sku、price、rating字段的正常展示,但手动逐个添加产品属性(如pa_gender)的方式无法适配大量属性的场景。尝试在字段数组内通过循环批量添加属性的写法出现报错,现寻求可自动获取所有产品属性并加入对比表字段的实现方案。


现有相关代码

1. fields函数代码

function fields( $products = array() ) {
    $fields = array(
        'thumbnail' => esc_html__( 'Image', 'woocommerce' ),
        'name' => esc_html__( 'Product', 'woocommerce' ),
        'sku' => esc_html__( 'SKU', 'woocommerce' ),
        'price' => esc_html__( 'Price', 'woocommerce' ),
        'rating' => esc_html__( 'Rating', 'woocommerce' ),
    );
    $fields = array_filter( $fields );
    foreach ( $fields as $key => $value ) {
        if ( isset( $this->default_fields[ $key ] ) ) {
            $fields[ $key ] = $this->default_fields[ $key ];
        } elseif ( taxonomy_exists( $key ) ) {
            $fields[ $key ] = wc_attribute_label( $key );
        }
    }
    if ( ! empty( $products ) ) {
        foreach ( $products as $product_id ) {
            $product = wc_get_product( $product_id );
            if ( ! $product ) {
                continue;
            }
            if ( $product instanceof WC_Product_Variation ) {
                $parent_product = wc_get_product( $product->get_parent_id() );
                $attrs          = $parent_product->get_attributes();
            } else {
                $attrs = $product->get_attributes();
            }
            foreach ( $attrs as $key => $value ) {
                $key = urldecode( $key );
                if ( ! isset( $value['is_taxonomy'] ) || ( $value['is_taxonomy'] && ! array_key_exists( $key, $fields ) ) || ( $value['is_taxonomy'] ) || ( ! $value['is_taxonomy'] ) ) {
                    continue;
                }
                $fields[ $key ] = wc_attribute_label( $key, $product );
            }
        }
    }
    return $fields;
}

2. 对比表渲染代码

<?php foreach ( $fields as $field => $name ) : ?>
    <tr class="<?php echo ! in_array( $field, $different, true ) ? esc_attr( $field ) : esc_attr( $field ) . ' different'; ?>">
        <th>
            <?php echo esc_html( $name ); ?>
        </th>
        <?php
        $index = 0;
        foreach ( $products as $product_id => $product ) :
            // Set td class.
            $product_class = ( ( 0 === ( $index % 2 ) ) ? 'odd' : 'even' ) . ' product_' . $product_id;
            if ( 'stock' === $field ) {
                $availability   = $product->get_availability();
                $product_class .= ' ' . ( empty( $availability['class'] ) ? 'in-stock' : $availability['class'] );
            }
            ?>
            <td class="<?php echo esc_attr( $product_class ); ?>">
                <?php
                    switch ( $field ) {
                        default:
                            echo empty( $product->fields[ $field ] ) ? '-' : do_shortcode( $product->fields[ $field ] );
                            break;
                    }
                ?>
            </td>
            <?php
            ++ $index;
        endforeach
        ?>
    </tr>
<?php endforeach; ?>

3. 手动添加属性示例(可正常显示)

$fields = array(
    'thumbnail' => esc_html__( 'Image', 'woocommerce' ),
    'name' => esc_html__( 'Product', 'woocommerce' ),
    'sku' => esc_html__( 'SKU', 'woocommerce' ),
    'price' => esc_html__( 'Price', 'woocommerce' ),
    'rating' => esc_html__( 'Rating', 'woocommerce' ),
    'pa_gender' => esc_html__( 'Gender', 'woocommerce' ),
);

4. 报错的批量添加尝试代码

$fields = array(
    'thumbnail' => esc_html__( 'Image', 'woocommerce' ),
    'name' => esc_html__( 'Product', 'woocommerce' ),
    'sku' => esc_html__( 'SKU', 'woocommerce' ),
    'price' => esc_html__( 'Price', 'woocommerce' ),
    'rating' => esc_html__( 'Rating', 'woocommerce' ),
    foreach ( wc_get_attribute_taxonomies() as $attribute ) {
        'pa_' . $attribute->attribute_name  => esc_html__( 'pa_name', 'woocommerce' ),
    }
);

问题分析

  • 数组字面量内直接嵌入foreach循环属于PHP语法错误,PHP不允许这种写法。
  • 原fields函数中属性遍历的条件判断逻辑矛盾,导致无法正确将属性添加到字段列表。

修正方案

1. 修复fields函数的属性获取逻辑

简化条件判断,自动遍历所有产品收集属性并添加到字段列表:

function fields( $products = array() ) {
    // 初始化默认字段
    $fields = array(
        'thumbnail' => esc_html__( 'Image', 'woocommerce' ),
        'name' => esc_html__( 'Product', 'woocommerce' ),
        'sku' => esc_html__( 'SKU', 'woocommerce' ),
        'price' => esc_html__( 'Price', 'woocommerce' ),
        'rating' => esc_html__( 'Rating', 'woocommerce' ),
    );

    // 替换默认字段标签
    foreach ( $fields as $key => $value ) {
        if ( isset( $this->default_fields[ $key ] ) ) {
            $fields[ $key ] = $this->default_fields[ $key ];
        } elseif ( taxonomy_exists( $key ) ) {
            $fields[ $key ] = wc_attribute_label( $key );
        }
    }

    // 遍历产品收集所有属性
    if ( ! empty( $products ) ) {
        foreach ( $products as $product_id ) {
            $product = wc_get_product( $product_id );
            if ( ! $product ) continue;

            // 变体产品取父产品属性
            $attrs = $product instanceof WC_Product_Variation 
                ? wc_get_product( $product->get_parent_id() )->get_attributes() 
                : $product->get_attributes();

            // 添加属性到字段列表
            foreach ( $attrs as $key => $attr ) {
                $attr_key = is_string( $key ) ? urldecode( $key ) : $attr->get_name();
                if ( ! array_key_exists( $attr_key, $fields ) ) {
                    $fields[ $attr_key ] = wc_attribute_label( $attr_key, $product );
                }
            }
        }
    }

    return $fields;
}

2. 优化属性值的渲染逻辑

针对产品属性字段添加专门处理,确保属性值正确显示:

<?php foreach ( $fields as $field => $name ) : ?>
    <tr class="<?php echo ! in_array( $field, $different, true ) ? esc_attr( $field ) : esc_attr( $field ) . ' different'; ?>">
        <th>
            <?php echo esc_html( $name ); ?>
        </th>
        <?php
        $index = 0;
        foreach ( $products as $product_id => $product ) :
            $product_class = ( ( 0 === ( $index % 2 ) ) ? 'odd' : 'even' ) . ' product_' . $product_id;
            if ( 'stock' === $field ) {
                $availability   = $product->get_availability();
                $product_class .= ' ' . ( empty( $availability['class'] ) ? 'in-stock' : $availability['class'] );
            }
            ?>
            <td class="<?php echo esc_attr( $product_class ); ?>">
                <?php
                // 专门处理产品属性字段
                if ( str_starts_with( $field, 'pa_' ) && taxonomy_exists( $field ) ) {
                    $terms = $product->get_attribute( $field );
                    echo $terms ? esc_html( $terms ) : '-';
                } else {
                    // 原有默认字段处理逻辑
                    echo empty( $product->fields[ $field ] ) ? '-' : do_shortcode( $product->fields[ $field ] );
                }
                ?>
            </td>
            <?php
            ++ $index;
        endforeach
        ?>
    </tr>
<?php endforeach; ?>

方案说明

  • 修正后的fields函数会自动遍历所有选中产品,收集它们的所有属性(包括变体产品的父产品属性),无需手动添加。
  • 渲染部分增加了对pa_前缀属性的专门处理,直接调用WooCommerce内置方法获取属性值,确保显示正确。
  • 移除了原代码中逻辑矛盾的判断条件,简化属性添加流程,避免遗漏属性。

内容的提问来源于stack exchange,提问作者Aras Riyahi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 15:37:43