WooCommerce应用指定优惠券时无法移除免费商品问题排查
问题:WooCommerce应用指定优惠券时无法移除自动添加的免费商品
在WooCommerce中,我用两段代码实现功能:第一段能在购物车满40欧元时自动添加0元的“winter”商品(ID为90),功能正常;第二段想要在应用“summer”优惠券时移除该免费商品,但无法生效,具体代码如下:
第一段可用代码
// Add free gifted product for specific cart subtotal add_action( 'woocommerce_before_calculate_totals', 'check_free_gifted_product' ); function check_free_gifted_product( $cart ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; // Settings $free_product_id = 90; $targeted_subtotal = 20; $cart_subtotal = 0; // Initializing // Loop through cart items (first loop) foreach ( $cart->get_cart() as $cart_item_key => $cart_item ){ // When free product is is cart if ( $free_product_id == $cart_item['product_id'] ) { $free_key = $cart_item_key; $free_qty = $cart_item['quantity']; $cart_item['data']->set_price(0); // Optionally set the price to zero } else { $cart_subtotal += $cart_item['line_total'] + $cart_item['line_tax']; } } // If subtotal match and free product is not already in cart, add it if ( ! isset($free_key) && $cart_subtotal >= $targeted_subtotal ) { $cart->add_to_cart( $free_product_id ); } } // Display free gifted product price to zero on minicart add_filter( 'woocommerce_cart_item_price', 'change_minicart_free_gifted_item_price', 10, 3 ); function change_minicart_free_gifted_item_price( $price_html, $cart_item, $cart_item_key ) { $free_product_id = 90; if( $cart_item['product_id'] == $free_product_id ) { return wc_price( 0 ); } return $price_html; }
第二段无效代码
function remove_free_product($cart) { /** * This function removes a free product "winter" from the cart if a coupon "summer" is applied. * * Parameters: * $cart (array): An array containing the cart items and their details * * Returns: * array: The updated cart array */ try { // Check if the cart is empty if (empty($cart)) { throw new Exception("Cart is empty"); } // Check if the coupon "summer" is applied $coupon_applied = false; foreach ($cart as $item) { if ($item['coupon'] == 'summer') { $coupon_applied = true; break; } } // Remove the free product "winter" if the coupon "summer" is applied if ($coupon_applied) { foreach ($cart as $key => $item) { if ($item['product'] == 'winter' && $item['price'] == 20) { unset($cart[$key]); break; } } } // Return the updated cart return $cart; } catch (Exception $e) { // Log the error error_log("Error: " . $e->getMessage()); return array(); } }
问题原因分析
无效代码存在3个核心问题:
- 未挂载到WooCommerce钩子:仅定义了函数,但没有通过
add_action关联到购物车处理的钩子,导致代码永远不会被执行。 - 优惠券与商品检查逻辑错误:
- 直接遍历
$cart找优惠券是错误的,WooCommerce购物车对象需要用$cart->get_applied_coupons()获取已应用优惠券列表。 - 用
$item['product'] == 'winter'判断商品不准确,应该用商品ID(90);且你设置该商品价格为0,代码里却判断$item['price'] == 20,逻辑矛盾。
- 直接遍历
- 购物车修改方式错误:直接
unset($cart[$key])不符合WooCommerce规范,应该用官方提供的$cart->remove_cart_item()方法操作购物车。
修复后的代码
将以下代码替换原无效代码,确保和第一段代码一样挂载到购物车计算钩子,且优先级更高(先执行移除,再执行添加):
add_action( 'woocommerce_before_calculate_totals', 'remove_free_product_on_coupon', 9 ); function remove_free_product_on_coupon( $cart ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; // 配置项 $free_product_id = 90; $target_coupon = 'summer'; // 检查是否应用了目标优惠券 if ( in_array( $target_coupon, $cart->get_applied_coupons() ) ) { // 遍历购物车移除目标商品 foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) { if ( $cart_item['product_id'] == $free_product_id ) { $cart->remove_cart_item( $cart_item_key ); break; // 找到后退出循环,避免重复操作 } } } }
关键说明
- 钩子优先级设为9,比第一段代码的默认优先级10高,确保移除逻辑先执行,防止刚移除的商品被重新添加。
- 使用
$cart->get_applied_coupons()正确获取已应用优惠券,避免错误遍历。 - 通过商品ID(90)精准识别目标商品,和第一段代码的配置保持一致。
- 用WooCommerce官方方法修改购物车,确保操作符合插件规范。
内容的提问来源于stack exchange,提问作者eros casula
相关产品推荐
相关产品推荐

