WooCommerce仅收取最高运费等级费用的实现问题
WooCommerce 仅收取最高运费等级费用的实现方案
问题分析
原代码存在两个核心问题:
- 处理可变产品时,错误遍历了所有可见变体,而非购物车中实际选中的变体
- 错误构造了运费费率的键名,导致无法正确获取对应运费等级的费用值
修正后的代码
add_filter('woocommerce_package_rates', 'custom_shipping_charge_highest_class_only', 10, 2); function custom_shipping_charge_highest_class_only($rates, $package) { // 存储各运费等级的最高费用 $class_max_costs = array(); $shipping_classes = get_terms('product_shipping_class', array('hide_empty' => false)); // 初始化所有运费等级的费用为0 foreach ($shipping_classes as $class) { $class_max_costs[$class->term_id] = 0; } // 遍历购物车订单项,收集对应运费等级的费用 foreach ($package['contents'] as $item_id => $item) { $product = $item['data']; $shipping_class_id = $product->get_shipping_class_id(); // 跳过无运费等级的产品 if (empty($shipping_class_id)) continue; // 遍历所有运费费率,找到当前产品对应运费等级的费用 foreach ($rates as $rate_key => $rate) { // 检查当前费率是否属于该运费等级 if ($rate->shipping_class_id == $shipping_class_id) { // 更新该等级的最高费用 if ($rate->cost > $class_max_costs[$shipping_class_id]) { $class_max_costs[$shipping_class_id] = $rate->cost; } break; } } } // 找到所有运费等级中的最高费用 $highest_cost = max($class_max_costs); // 移除所有非最高费用的运费选项 foreach ($rates as $rate_key => $rate) { // 无运费等级的选项(如默认运费)直接移除 if (empty($rate->shipping_class_id)) { unset($rates[$rate_key]); continue; } // 保留费用等于最高费用的运费选项 if ($rate->cost != $highest_cost) { unset($rates[$rate_key]); } } // 强制刷新缓存并更新运费标签 foreach ($rates as $rate) { $rate->set_label('最高运费等级收取'); // 可自定义运费显示标签 $rate->set_cost($highest_cost); } return $rates; }
代码说明
- 初始化运费等级费用:先获取所有已创建的运费等级,初始化它们的费用为0
- 收集订单项对应运费等级的费用:遍历购物车中的每个产品(包括可变产品的选中变体),通过
get_shipping_class_id()直接获取其运费等级ID,匹配对应的运费费率并记录该等级的最高费用 - 筛选最高费用的运费选项:找出所有运费等级中的最高费用,移除所有费用不等于该值的运费选项
- 更新运费标签与缓存:统一设置运费显示标签,确保费用为最高值,同时强制刷新缓存避免显示异常
使用注意事项
- 确保已在WooCommerce后台正确设置配送区域、运费等级及对应价格
- 产品(包括可变产品的变体)需正确分配运费等级
- 配送方式的计算方法需设置为按等级
内容的提问来源于stack exchange,提问作者RP McMurphy
相关产品推荐
相关产品推荐

