Woocommerce如何在运费计算钩子中获取购物车product_id实现差异化运费
问题原因与修复方案
核心错误点
- 未初始化
$product_id变量,wc_get_product( $product_id )获取的是无效商品对象,和数字6721的对比逻辑永远不成立 - 没有遍历购物车商品校验ID,全局调用
$woocommerce获取购物车不如直接用钩子自带的$package参数准确,$package中已经包含当前运费套餐对应的所有商品信息 - 多余的
echo输出会触发PHP headers already sent错误,同时用+=累加运费容易出现重复计算问题
修正后的代码
add_filter( 'woocommerce_package_rates', 'c7_hide_free_shipping_class', 10, 2 ); function c7_hide_free_shipping_class( $rates, $package ) { $has_target_product = false; // 遍历当前运费套餐的所有商品,校验是否包含product_id为6721的商品 foreach( $package['contents'] as $cart_item ) { if( $cart_item['product_id'] == 6721 ) { $has_target_product = true; break; // 找到后直接跳出循环,提高性能 } } // 获取配送地址,优先用配送地址而非账单地址,更符合运费计算场景 $state = $package['destination']['state']; $city = explode(' - ', $package['destination']['city']); $distrito = ''; if (count($city) > 1) { $distrito = $city[1]; } if ($state != 'LMA' || !in_array($distrito, ['Surquillo']) ) { unset( $rates['SD'] ); unset( $rates['ND'] ); } if ($state == 'LMA' && in_array($distrito, ['Chorrillos']) && isset($rates['flat_rate:7']) ) { $rates['flat_rate:7']->cost = 7.5; // 直接赋值统一运费,避免累加错误 $rates['flat_rate:7']->label = 'De 1 a 2 dias'; } else if ($state == 'LMA' && $has_target_product && in_array($distrito, ['Chaclacayo']) && isset($rates['flat_rate:7']) ) { $rates['flat_rate:7']->cost = 17.5; // 直接赋值目标运费,避免累加错误 $rates['flat_rate:7']->label = 'De 2 a 3'; } else if ($state == 'LMA' && in_array($distrito, []) && isset($rates['flat_rate:7']) ){ unset( $rates['flat_rate:7'] ); } return $rates; }
额外优化说明
- 增加了
isset($rates['flat_rate:7'])判断,避免运费方式不存在时抛出PHP错误 - 直接给运费赋值固定值,避免多次触发钩子时运费重复叠加的问题
- 校验到目标商品后直接跳出循环,降低性能损耗
- 替换原有的全局账单地址获取逻辑,改用配送地址计算运费,更符合实际业务场景
内容的提问来源于stack exchange,提问作者ATPDev
相关产品推荐
相关产品推荐

