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),要么是非分类法属性(如手动输入的 “尺码”),不能同时属于两者。
所以,该代码片段中,分类法属性和非分类法属性的处理逻辑是互斥的。