Woocommerce实现BOGO活动:购物车复制商品而非增数量
解决WooCommerce买赠(BOGO)活动:新增免费商品项而非合并数量
问题分析
你当前的代码使用WC()->cart->add_to_cart()时,WooCommerce默认会将同商品的购物项合并,导致无法生成独立的免费商品项。另外,代码没有处理重复添加的问题(比如用户多次更新购物车时会重复添加免费项),也没设置免费项的价格为0。
修正后的完整代码
// 监听购物车更新事件,添加免费商品项 add_filter('woocommerce_update_cart_action_cart_updated', 'add_free_bogo_item_on_cart_update'); add_action('woocommerce_cart_loaded_from_session', 'add_free_bogo_item_on_cart_update'); function add_free_bogo_item_on_cart_update() { if (!WC()->cart) return; $cart_items = WC()->cart->get_cart(); $added_free_items = []; // 先记录已存在的免费项,避免重复添加 foreach ($cart_items as $key => $item) { if (isset($item['free_bogo_item']) && $item['free_bogo_item'] === true) { $added_free_items[$item['product_id']] = true; } } // 遍历购物车项,添加对应免费商品 foreach ($cart_items as $key => $item) { $product_id = $item['product_id']; $quantity = $item['quantity']; // 跳过免费项本身,且仅当数量≥5且未添加过对应免费项时执行 if (isset($item['free_bogo_item']) || $quantity < 5 || isset($added_free_items[$product_id])) { continue; } // 添加免费商品,标记为免费项 WC()->cart->add_to_cart( $product_id, 1, $item['variation_id'], $item['variation'], ['free_bogo_item' => true] // 自定义元数据标记免费项 ); // 标记已添加,防止重复 $added_free_items[$product_id] = true; } WC()->cart->calculate_totals(); } // 修改免费项的价格显示为FREE,小计为0 add_filter('woocommerce_cart_item_subtotal', 'set_bogo_free_item_price', 10, 3); add_filter('woocommerce_cart_item_price', 'set_bogo_free_item_price', 10, 3); function set_bogo_free_item_price($price, $cart_item, $cart_item_key) { if (isset($cart_item['free_bogo_item']) && $cart_item['free_bogo_item'] === true) { return '<span class="free-bogo-item">FREE</span>'; } return $price; } // 确保免费项的实际价格为0(不影响订单计算) add_action('woocommerce_before_calculate_totals', 'set_bogo_free_item_actual_price'); function set_bogo_free_item_actual_price($cart) { if (is_admin() && !defined('DOING_AJAX')) return; if (did_action('woocommerce_before_calculate_totals') >= 2) return; foreach ($cart->get_cart() as $cart_item_key => $cart_item) { if (isset($cart_item['free_bogo_item']) && $cart_item['free_bogo_item'] === true) { $cart_item['data']->set_price(0); } } }
代码说明
- 覆盖全场景:同时使用
woocommerce_update_cart_action_cart_updated和woocommerce_cart_loaded_from_session钩子,覆盖用户添加商品到购物车、更新购物车数量两种触发场景。 - 防止重复添加:先遍历购物车记录已存在的免费项,避免用户多次更新购物车时重复生成免费商品。
- 标记免费项:通过自定义元数据
free_bogo_item标记免费商品,方便后续识别并修改价格。 - 价格双处理:
- 用
woocommerce_cart_item_subtotal和woocommerce_cart_item_price钩子修改前端显示为"FREE",匹配你需要的展示效果。 - 用
woocommerce_before_calculate_totals钩子设置免费项的实际价格为0,确保订单金额计算正确。
- 用
使用注意事项
- 将代码添加到你的主题
functions.php文件或自定义插件中。 - 若需针对特定商品生效,可在判断条件中添加商品ID白名单,比如
if ($product_id !== 123) continue;(替换123为目标商品ID)。 - 测试前清空购物车缓存,确保代码正常生效。
内容的提问来源于stack exchange,提问作者Nymul Islam Moon
相关产品推荐
相关产品推荐

