
本文介绍如何通过 woocommerce_package_rates 钩子,根据购物车中指定运输分类(如 shipping class 51)的商品总数量,按“每6件计费一次”的规则动态重算运费,同时忽略其他分类(如 class 41)对运费的影响。
本文介绍如何通过 woocommerce_package_rates 钩子,根据购物车中指定运输分类(如 shipping class 51)的商品总数量,按“每6件计费一次”的规则动态重算运费,同时忽略其他分类(如 class 41)对运费的影响。
在 WooCommerce 多运输分类场景下,若需实现「仅对特定运输分类(如 class 51)计费,且按批量单位(如每6件计1次运费)」的逻辑,直接修改 cart_shipping_total 或依赖默认 [qty]*rate 表达式无法满足需求——因为后者会对每个商品单独乘以数量,而我们需要的是向上取整分组计费(即 6 件 = 1 单位,7 件 = 2 单位)。
正确做法是利用 woocommerce_package_rates 过滤器,在运费计算完成但尚未展示前,动态修正各运输方式的 cost 值。该钩子接收所有可用运输费率(含不同区域、不同方式),允许你基于购物车内容统一调整费用。
以下是推荐的实现方案(添加至主题的 functions.php 或自定义插件中):
add_filter( 'woocommerce_package_rates', 'adjust_shipping_cost_by_class_batch' );
function adjust_shipping_cost_by_class_batch( $rates ) {
// 仅在前台购物车/结算页生效,排除后台与 AJAX 请求
if ( is_admin() || ! WC()->cart || WC()->cart->is_empty() ) {
return $rates;
}
// 定义需参与计费的运输分类 ID(支持多个)
$target_class_ids = array(51);
// 统计目标分类商品总数量
$total_target_qty = 0;
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 ) ) {
$total_target_qty += $cart_item['quantity'];
}
}
// 若未找到目标分类商品,则不修改运费(保持免费或原价)
if ( $total_target_qty === 0 ) {
return $rates;
}
// 计算“每6件计1次”的单位数(向上取整:(n + 5) / 6)
$batch_units = (int) ceil( $total_target_qty / 6 );
// 对所有运输方式的费用应用倍率
foreach ( $rates as $rate_id => $rate ) {
$rates[ $rate_id ]->cost = $rate->cost * $batch_units;
// 如需同步调整税费(若运费含税),可取消下方注释
// if ( isset( $rate->taxes ) && ! empty( $rate->taxes ) ) {
// foreach ( $rate->taxes as $tax_id => $tax_amount ) {
// if ( $tax_amount > 0 ) {
// $rates[ $rate_id ]->taxes[ $tax_id ] = $tax_amount * $batch_units;
// }
// }
// }
}
return $rates;
}
✅ 关键说明:
- 使用 ceil($total_target_qty / 6) 实现标准向上取整(比 intdiv($n+5,6) 更直观且语义明确);
- 严格校验 WC()->cart 存在性及非空状态,避免后台报错;
- 仅当存在目标分类商品时才重算,否则保留原始费率(如 class 41 单独下单仍为 0);
- 自动适配多运输方式(Flat Rate、Table Rate 等)和多区域(Zone 1/Zone 2),无需额外配置;
- 若运费含税,建议同步调整 taxes 数组(代码中已提供示例,按需启用)。
⚠️ 注意事项:
- 请确保后台运输设置中,class 51 的基础运费设为固定值(如 Zone 1 写 10,而非 [qty]*10),否则会重复计算;
- 修改后需清空 WooCommerce 缓存(如对象缓存、页面缓存),并在真实购物车中测试多组合场景(如 class41×2 + class51×13 → 应得 3 单位 × 10 = $30);
- 如启用运费缓存(如某些性能插件),可能需禁用或刷新缓存以确保实时生效。
此方案简洁、健壮且完全兼容 WooCommerce 核心机制,是处理“按分类批量计费”需求的标准实践。











