wordpress-woo中产品属性可以既是分类法也同时是非分类法吗?

woocmomerce的产品详情页中用户购物时选择的产品属性,如:尺码、颜色等,即产品变体的产品属性,生成选择下拉菜单功能。

研究源码时,发现渲染下拉菜单功能时,发现单个属性只能属于一种类型:要么是分类法属性(如pa_color),要么是非分类法属性(如手动输入的 “尺码”),不能同时属于两者。如下:

if ( ! empty( $options ) ) {
    if ( $product && taxonomy_exists( $attribute ) ) {
        // Get terms if this is a taxonomy - ordered. We need the names too.
        $terms = wc_get_product_terms(
            $product->get_id(),
            $attribute,
            array(
                'fields' => 'all',
            )
        );

        foreach ( $terms as $term ) {
            if ( in_array( $term->slug, $options, true ) ) {
                $html .= '<option value="' . esc_attr( $term->slug ) . '" ' . selected( sanitize_title( $args['selected'] ), $term->slug, false ) . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name, $term, $attribute, $product ) ) . '</option>';
            }
        }
    } else {
        foreach ( $options as $option ) {
            $selected = sanitize_title( $args['selected'] ) === $args['selected'] ? selected( $args['selected'], sanitize_title( $option ), false ) : selected( $args['selected'], $option, false );
            $html    .= '<option value="' . esc_attr( $option ) . '" ' . $selected . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $option, null, $attribute, $product ) ) . '</option>';
        }
    }
}

属性类型的底层实现

分类法属性(Taxonomy Attributes)

属性定义在wp_terms和wp_term_taxonomy表中。术语(如 “红色”、“蓝色”)作为分类法术语存储。

调用如下:

// 属性名格式固定为 pa_{slug}
$attribute_name = 'pa_color';

非分类法属性(Custom Attributes)

接存储在产品元数据(wp_postmeta)中,键名为_product_attributes。

调用如下:

// 属性名是任意自定义字符串
$attribute_name = '自定义尺码';

为什么不能同时是两种类型?

分类法属性依赖 WordPress 的分类法系统,有固定的命名规则(pa_前缀)。而非分类法属性只是产品级的元数据,没有全局标识符。

分类法属性需要通过wp_get_object_terms()查询。而非分类法属性直接从产品元数据读取。

在产品编辑界面,属性只能选择 “全局属性”(分类法)或 “自定义属性”,不能同时选。

实际应用中的混淆点

即使是同名属性,如都是颜色。在产品 A:使用全局 “颜色” 属性(分类法pa_color)。在产品 B中:手动输入 “颜色” 选项(非分类法)。

结果是:产品 A 的属性名是pa_color,走分类法逻辑。产品 B 的属性名是 “颜色”,走非分类法逻辑。

返回上面源码分析

这段代码是针对单个属性执行的,而不是同时处理所有属性。

又因为单个属性只能属于一种类型:要么是分类法属性(如pa_color),要么是非分类法属性(如手动输入的 “尺码”),不能同时属于两者。

所以,该代码片段中,分类法属性和非分类法属性的处理逻辑是互斥的。