WooCommerce按产品分类及属性调整运费问题排查
WooCommerce分类运费调整问题修复方案
我的WooCommerce网店包含category_1、category_2、category_3、category_4四个分类,需要按以下规则调整运费:
- category_1、category_2产品运费为10
- category_3产品运费为75
- category_4产品根据size属性设置运费:small=38、medium=50、large=62
现有代码前三个分类的运费设置生效,但category_4带指定属性的产品运费无法显示,以下是问题排查和修复:
问题根源分析
- 致命语法错误:
return $rates;写在了函数change_shipping_cost外部,导致函数执行到一半直接终止,category_4的运费计算逻辑根本没机会完成返回 - 属性值大小写不匹配:
get_attribute('size')返回的属性值通常是大写开头(比如Medium),但代码中运费映射数组用的是小写键(medium),导致匹配失败 - 分类判断逻辑冗余:多个独立的
has_term判断可以合并优化,提升代码可读性
修正后的完整代码
add_filter( 'woocommerce_package_rates', 'change_shipping_cost', 10, 2 ); function change_shipping_cost( $rates, $package ) { $shipping_method = 'flat_rate:11'; // 分类-运费映射表 $category_cost_map = array( 'category_1' => 10, 'category_2' => 10, 'category_3' => 75 ); // category_4尺寸-运费映射表 $category4_size_cost = array( 'small' => 38, 'medium' => 50, 'large' => 62 ); $max_quantity = 0; foreach ( $package['contents'] as $item ) { if ( has_term( array_keys($category_cost_map) + ['category_4'], 'product_cat', $item['product_id'] ) ) { $max_quantity = max( $max_quantity, $item['quantity'] ); } } if ( isset( $rates[ $shipping_method ] ) && $max_quantity == 1 ) { $max_cost = 0; foreach ( $package['contents'] as $item ) { $product_id = $item['product_id']; // 检查是否属于目标分类 if ( has_term( array_keys($category_cost_map) + ['category_4'], 'product_cat', $product_id ) ) { // 处理前三个分类 foreach ( $category_cost_map as $cat_slug => $cost ) { if ( has_term( $cat_slug, 'product_cat', $product_id ) ) { $max_cost = max( $max_cost, $cost ); break; // 匹配到分类后跳出循环 } } // 处理category_4 if ( has_term( 'category_4', 'product_cat', $product_id ) ) { $product = wc_get_product( $product_id ); if ( !$product ) continue; // 获取尺寸属性值,统一转小写 if ( $product->is_type( 'variable' ) ) { $variation = wc_get_product( $item['variation_id'] ); $size = $variation ? strtolower( $variation->get_attribute('size') ) : ''; } else { $size = strtolower( $product->get_attribute('size') ); } // 匹配运费并更新最大值 if ( isset( $category4_size_cost[ $size ] ) ) { $max_cost = max( $max_cost, $category4_size_cost[ $size ] ); } } } } $rates[ $shipping_method ]->cost = $max_cost; } return $rates; // 确保return在函数内部 }
关键修改点
- 修正了
return $rates;的位置,确保函数正常返回修改后的运费数据 - 用
strtolower()将获取到的size属性值转为小写,和映射数组的键保持一致,解决匹配失败问题 - 用数组映射表替代多个独立的if判断,简化分类运费的判断逻辑
- 添加了
continue跳过无效产品的处理,提升代码健壮性
内容的提问来源于stack exchange,提问作者Jack_Di
相关产品推荐
相关产品推荐

