WooCommerce按重量算运费及免运费类失效问题求助
修复WooCommerce按重量计费+免运费的逻辑问题
嘿,我看出来你的问题所在了——原代码根本没检查购物车里有没有免运费类的商品,而且重量区间的判断也和你说的规则对不上,这才导致免运费功能失效。咱们来把逻辑理顺,让它完全符合你的需求:只要购物车里有付费运费的商品,就按重量算;只有全是免运费商品的时候,才触发免运费。
修复后的完整代码
add_filter( 'woocommerce_package_rates', 'custom_tiered_shipping_rates_with_free_shipping', 9999, 2 ); function custom_tiered_shipping_rates_with_free_shipping( $rates, $package ) { // 先标记购物车是否有非免运费的商品 $has_paid_items = false; // 挨个检查购物车里的商品 foreach ( WC()->cart->get_cart() as $cart_item ) { $product = $cart_item['data']; // 拿到商品的配送类slug $shipping_classes = $product->get_shipping_class_slugs(); // 只要有一个商品不是free_shipping类,就标记为有付费商品 if ( !in_array( 'free_shipping', $shipping_classes ) ) { $has_paid_items = true; break; // 找到一个就不用继续查了,省点资源 } } // 如果有付费商品,就按重量规则来 if ( $has_paid_items ) { $total_weight = WC()->cart->get_cart_contents_weight(); // 按你的规则:<19kg用36美元的配送方式,≥19kg用300美元的 if ( $total_weight < 19 ) { // 只保留Orders Below 19kg(flat_rate:21) if ( isset( $rates['flat_rate:21'] ) ) { unset( $rates['flat_rate:22'], $rates['flat_rate:24'] ); } } else { // 只保留Orders Above 19kg(flat_rate:22) if ( isset( $rates['flat_rate:22'] ) ) { unset( $rates['flat_rate:21'], $rates['flat_rate:24'] ); } } } else { // 全是免运费商品,只保留Free Shipping(flat_rate:24) if ( isset( $rates['flat_rate:24'] ) ) { unset( $rates['flat_rate:21'], $rates['flat_rate:22'] ); } } // 清一下缓存,不然有时候改了商品设置,运费不会实时更新 foreach ( $rates as $rate_key => $rate ) { $rates[$rate_key]->cost = $rate->cost; } return $rates; }
为啥这么改?
- 免运费逻辑补全:现在代码会先检查购物车所有商品,只有当全部都是
free_shipping类的时候,才会显示免运费;只要有一个不是,就乖乖按重量算运费,完全符合你补充的规则。 - 重量规则修正:原代码里写的是
>20kg,和你说的「>19kg时运费300美元」不符,我改成了>=19kg,这样19kg本身也会触发300美元的运费,同时也解决了原代码中19-20kg区间的模糊处理问题。 - 缓存处理:加了一段清缓存的代码,避免你给商品改了配送类之后,运费还是老样子的情况。
最后再确认两点
- 你创建的
Free Shipping配送方式ID确实是flat_rate:24吗?可以在编辑这个配送方式的时候看URL,比如URL里的post=24就对应这个ID,要是不对的话,把代码里的flat_rate:24改成你实际的ID就行。 - 商品的配送类一定要选对:在商品编辑页的「配送」选项卡里,选
free_shipping这个类,不然代码识别不出来。
内容的提问来源于stack exchange,提问作者Victor S.
相关产品推荐
相关产品推荐

