
本文介绍如何在 woocommerce 中根据购物车中特定运费分类(如 shipping class id 51)的商品总数量,按“每6件计1单位运费”动态调整最终运费,忽略其他分类(如 class 41)的影响,并兼容多运费区域。
本文介绍如何在 woocommerce 中根据购物车中特定运费分类(如 shipping class id 51)的商品总数量,按“每6件计1单位运费”动态调整最终运费,忽略其他分类(如 class 41)的影响,并兼容多运费区域。
在 WooCommerce 多运费场景下,若需对某类商品(如 premium 商品,对应 shipping class ID 51)实现「按箱计费」逻辑——即每满 6 件计为 1 个计费单位,单价固定(Zone 1 为 $10/单位,Zone 2 为 $12/单位),而其他商品(如 class 41)完全不参与运费计算(始终免费),则不能依赖默认的 [qty]*rate 模式,而应通过钩子动态重写各运费选项的 cost 值。
核心思路是:在运费计算完成但尚未展示前,拦截所有可用运费方案(woocommerce_package_rates),统计目标运费分类的商品总数量,按向上取整方式换算为计费单位数(ceil($total_qty / 6)),再将每个运费项的原始 cost 乘以该单位数。
以下是推荐实现代码,需添加至当前主题的 functions.php 文件或自定义插件中:
add_filter( 'woocommerce_package_rates', 'adjust_shipping_cost_by_class_group' );
function adjust_shipping_cost_by_class_group( $rates ) {
// 仅在购物车非空时执行
if ( WC()->cart->is_empty() ) {
return $rates;
}
// 定义需参与计费的运费分类 ID(支持多个,如 array(51, 52))
$target_class_ids = array(51);
$total_target_qty = 0;
$has_target_item = false;
// 遍历购物车,累加目标分类商品总数量
foreach ( WC()->cart->get_cart() as $cart_item ) {
$shipping_class_id = $cart_item['data']->get_shipping_class_id();
if ( in_array( $shipping_class_id, $target_class_ids ) ) {
$has_target_item = true;
$total_target_qty += $cart_item['quantity'];
}
}
// 若无目标分类商品,则保持原运费不变(class 41 等仍为 0)
if ( ! $has_target_item ) {
return $rates;
}
// 计算计费单位数:向上取整(每6件为1单位)
// intdiv($n + 5, 6) 是 PHP 7+ 中高效实现 ceil($n / 6) 的整数运算方式
$billing_units = intdiv( $total_target_qty + 5, 6 );
// 对每个运费选项(如 flat_rate:1, flat_rate:2)应用新费用
foreach ( $rates as $rate_key => $rate ) {
$rates[ $rate_key ]->cost = $rate->cost * $billing_units;
// 若运费含税费,也需同比例调整(可选,推荐启用以保证税费准确)
if ( isset( $rate->taxes ) && is_array( $rate->taxes ) ) {
foreach ( $rate->taxes as $tax_key => $tax_amount ) {
if ( $tax_amount > 0 ) {
$rates[ $rate_key ]->taxes[ $tax_key ] = $tax_amount * $billing_units;
}
}
}
}
return $rates;
}✅ 关键配置说明:
- 在 WooCommerce 后台 → 运费设置 → 运费区域 中,为每个区域(Zone 1 / Zone 2)单独配置:
- class41:费率设为 0(或留空,确保不产生费用);
- class51:费率设为固定值(Zone 1 填 10,Zone 2 填 12),*不要使用 `[qty]10` 形式** —— 否则会与本逻辑重复叠加。
⚠️ 注意事项:
- 此方案作用于 woocommerce_package_rates,确保在运费引擎完成初始计算后介入,兼容绝大多数运费方法(Flat Rate、Table Rate、第三方插件等);
- 不要使用 woocommerce_cart_shipping_total 钩子修改显示文本,因其仅影响前端摘要,无法改变实际结算逻辑;
- 若启用运费税费,请务必同步调整 $rate->taxes,否则可能导致税费计算失准;
- 如需排除虚拟商品或跳过某些条件(如用户角色),可在循环中加入额外判断;
- 修改后请清空 WooCommerce 缓存并测试不同组合(如 class51×5、×6、×13)验证计费结果是否符合预期($10/$12、$20/$24、$30/$36)。
通过该方案,即可精准实现「class41 免费 + class51 每6件一单位」的灵活运费策略,兼顾扩展性与稳定性。

















