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
相关产品推荐
相关产品推荐

