如何为通过URL自动生成的WooCommerce优惠券添加免费商品
问题排查与修复方案
你现有代码的核心问题集中在变量作用域、逻辑分支判断错误两个部分,以下是具体问题点和修复后的完整代码:
存在的问题
$regular_price仅在购物车已存在免费商品的场景下会被赋值,首次触发添加免费商品逻辑时调用该变量会触发PHP未定义变量报错$cart_count定义在购物车遍历循环内部,若购物车无免费商品时调用该变量也会出现未定义报错- 你已经将优惠券配置为仅对ID为74的商品生效、折扣比例100%,无需额外将商品价格设置为0,重复逻辑会导致WooCommerce折扣计算冲突
- 调用
add_discount添加优惠券后没有更新本地存储的已应用优惠券列表,会导致后续逻辑判断出错 - 移除优惠券的分支逻辑写反:当前判断条件为「优惠券未应用」时执行移除操作,逻辑完全不成立
修复后的完整代码
function coupon_exists( $coupon_code ) { global $wpdb; $sql = $wpdb->prepare( "SELECT post_name FROM $wpdb->posts WHERE post_type = 'shop_coupon' AND post_name = '%s'", $coupon_code ); $coupon_codes = $wpdb->get_results($sql); return count( $coupon_codes ) > 0; } // 生成优惠券 function generate_coupon($coupon_generated) { // 设置优惠券默认参数 $date_expires = date('Y-m-d H:i:s', strtotime('+24 hours')); $discount_type = 'percent'; $coupon_amount = '100'; $coupon = new WC_Coupon(); $coupon->set_code($coupon_generated); $coupon->set_discount_type($discount_type); $coupon->set_amount($coupon_amount); $coupon->set_date_expires($date_expires); $coupon->set_individual_use(true); $coupon->set_product_ids (array(74)); $coupon->set_usage_limit(1); $coupon->set_limit_usage_to_x_items(1); $coupon->set_usage_limit_per_user(1); $coupon->set_exclude_sale_items(true); $coupon->set_minimum_amount('100'); $coupon->set_maximum_amount('150'); $coupon->save(); return $coupon_generated; } // 添加优惠券和免费商品到购物车 function generate_coupon_add_product_to_cart ( $cart ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return; $coupon_code = ( isset( $_GET['coupon-code'] ) && $_GET['coupon-code'] != '' ) ? $_GET['coupon-code'] : '' ; if( $coupon_code == '' ){ return; } $applied_coupons = $cart->get_applied_coupons(); $free_product_id = 74; $free_product_in_cart = false; $free_product_key = ''; $regular_price = wc_get_product($free_product_id)->get_regular_price(); $cart_count = $cart->get_cart_contents_count(); if( empty( $applied_coupons ) || ! in_array( $coupon_code, $applied_coupons ) ){ if ( !coupon_exists( $coupon_code ) ) { generate_coupon( $coupon_code ); } } // 遍历购物车判断免费商品是否存在 foreach( $cart->get_cart() as $cart_item_key => $cart_item ) { $product = $cart_item['data']; if ( $product->get_id() == $free_product_id ) { $free_product_key = $cart_item_key; $free_product_in_cart = true; } } // 优惠券未应用且免费商品不在购物车:添加商品+应用优惠券 if ( !in_array($coupon_code, $applied_coupons) && !$free_product_in_cart ){ $cart->add_to_cart( $free_product_id, 1 ); $cart->add_discount( $coupon_code ); // 刷新已应用优惠券列表 $applied_coupons = $cart->get_applied_coupons(); wc_add_notice( sprintf(__('<strong>免费</strong> 商品已添加到您的购物车,价值 %s', 'woocommerce'),'<strong>' . get_woocommerce_currency_symbol() . $regular_price . '</strong>'), 'notice'); } // 优惠券未应用但免费商品在购物车:移除免费商品 elseif( !in_array($coupon_code, $applied_coupons) && $free_product_in_cart ){ $cart->remove_cart_item( $free_product_key ); wc_add_notice( __("优惠券已失效,免费商品已移除", 'woocommerce'), 'notice' ); } // 购物车仅剩免费商品:移除商品和优惠券 elseif ( $free_product_in_cart && $cart_count <= 1 ){ $cart->remove_cart_item( $free_product_key ); $cart->remove_coupon( $coupon_code ); wc_add_notice( __("免费商品已移除", 'woocommerce'), 'notice' ); } } add_action('woocommerce_before_calculate_totals', 'generate_coupon_add_product_to_cart');
优化说明
- 提前初始化所有需要用到的变量,避免未定义报错
- 移除了重复的商品价格设0逻辑,完全靠优惠券规则实现免费
- 修正了优惠券移除、商品移除的逻辑分支,确保对应场景下操作正常执行
- 添加优惠券后主动刷新已应用优惠券列表,避免逻辑判断误差
内容的提问来源于stack exchange,提问作者Stoto
相关产品推荐
相关产品推荐

