WooCommerce中排除指定品类商品计算免运费最低金额问题
解决WooCommerce中特定品类商品排除免运费门槛计算的问题
需求说明
已在WooCommerce配置多个配送区域,每个区域包含平邮(Flat rate)、免费自提(Local pickup)、满额免运费(Free shipping)三种配送方式。需要将leeggoed品类的商品排除在免运费资格的小计计算之外——即该品类商品的金额不计入满额免邮的达标门槛。
当前已实现免运费可用时隐藏平邮的功能,代码如下:
function hide_shipping_when_free_is_available( $rates, $package ) { $new_rates = array(); foreach ( $rates as $rate_id => $rate ) { // 仅当免运费方式存在时调整配送选项 if ( 'free_shipping' === $rate->method_id ) { $new_rates[ $rate_id ] = $rate; break; } } if ( ! empty( $new_rates ) ) { // 保留自提选项(如果存在) foreach ( $rates as $rate_id => $rate ) { if ('local_pickup' === $rate->method_id ) { $new_rates[ $rate_id ] = $rate; break; } } return $new_rates; } return $rates; } add_filter( 'woocommerce_package_rates', 'hide_shipping_when_free_is_available', 10, 2 );
但用于调整免运费门槛计算的代码未生效,即使调整后的小计达标,仍无法触发免运费:
add_filter('woocommerce_shipping_free_shipping_is_available', function ($is_available, $package, $shipping_method) { $excluded_category = 'leeggoed'; // 要排除的品类别名 $adjusted_total = 0; // 初始化调整后的小计 // 步骤1:计算排除"leeggoed"品类后的购物车总额 foreach (WC()->cart->get_cart() as $cart_item) { $product = $cart_item['data']; $product_id = $product->get_id(); // 仅统计不在"leeggoed"品类的商品 if (!has_term($excluded_category, 'product_cat', $product_id)) { $adjusted_total += $cart_item['line_subtotal']; } } // 步骤2:获取当前配送方式的免运费门槛 if (isset($shipping_method->min_amount)) { $free_shipping_min_amount = (float) $shipping_method->min_amount; } else { $free_shipping_min_amount = 0; // 无门槛时默认设为0 } // 步骤3:仅当调整后小计达标时,免运费可用 return ($adjusted_total >= $free_shipping_min_amount); }, 10, 3);
问题分析与修正代码
现有代码存在三个核心问题:
- 遍历整个购物车而非当前配送区域的商品包(
$package),多配送区域场景下计算逻辑错误; - 变体商品使用变体ID检查分类,而品类通常设置在父产品上,导致判断失效;
- 直接覆盖原始判断结果,忽略了WooCommerce内置的免运费生效条件(如配送区域匹配、用户权限等)。
修正后的代码如下:
add_filter('woocommerce_shipping_free_shipping_is_available', function ($is_available, $package, $shipping_method) { // 先保留原始免运费生效条件(如配送区域匹配) if (!$is_available) { return false; } $excluded_category = 'leeggoed'; $adjusted_total = 0; // 遍历当前配送区域的商品包,而非整个购物车 foreach ($package['contents'] as $cart_item) { // 变体商品取父产品ID,普通商品取自身ID $product_id = $cart_item['variation_id'] ? $cart_item['product_id'] : $cart_item['data']->get_id(); // 仅统计非排除品类的商品金额 if (!has_term($excluded_category, 'product_cat', $product_id)) { $adjusted_total += $cart_item['line_subtotal']; } } $free_shipping_min_amount = isset($shipping_method->min_amount) ? (float)$shipping_method->min_amount : 0; // 结合原始条件与自定义金额判断返回结果 return $adjusted_total >= $free_shipping_min_amount; }, 10, 3);
关键修改点说明
- 基于配送区域计算:用
$package['contents']遍历当前配送区域的商品,确保多配送场景下计算准确; - 兼容变体商品:通过
variation_id判断是否为变体,取父产品ID检查分类,避免因变体未设置品类导致的判断错误; - 保留原始规则:先校验
$is_available,不破坏WooCommerce内置的免运费基础规则; - 金额逻辑统一:沿用购物车项的
line_subtotal,与系统默认小计计算逻辑保持一致。
内容的提问来源于stack exchange,提问作者ken
相关产品推荐
相关产品推荐

