WooCommerce阶梯买赠折扣码问题及WP Code Snippet报错排查
WooCommerce阶梯买赠代码修复(解决"Undefined array key 'line_total'"错误)
错误原因
woocommerce_before_calculate_totals钩子触发时,WooCommerce还未完成购物车项的金额计算,line_total字段此时尚未生成,直接访问该数组键就会抛出未定义错误。
修复后的代码
add_action('woocommerce_before_calculate_totals', 'frebeat_bogo_discount', 10, 1); function frebeat_bogo_discount($cart) { if (is_admin() && !defined('DOING_AJAX')) { return; } // 避免钩子重复触发导致异常 if (did_action('woocommerce_before_calculate_totals') >= 2) { return; } $free_categories = ['non-exclusive-beats', 'exclusive-beats']; $eligible_products = []; foreach ($cart->get_cart() as $cart_item_key => $cart_item) { foreach ($free_categories as $category) { if (has_term($category, 'product_cat', $cart_item['product_id'])) { // 保存购物车项key、内容及计算后的总价,用于后续排序和价格修改 $eligible_products[] = [ 'key' => $cart_item_key, 'item' => $cart_item, 'total' => $cart_item['quantity'] * $cart_item['data']->get_price() ]; break; } } } $eligible_count = count($eligible_products); // 买2送1规则,至少2件符合条件才触发 if ($eligible_count < 2) { return; } // 计算免费商品数量:买2送1、买3送2... 公式对应免费数 = floor((总数量-1)/2) $free_count = floor(($eligible_count - 1) / 2); // 按总价从小到大排序,确保免单的是价格最低的项 usort($eligible_products, function($a, $b) { return $a['total'] <=> $b['total']; }); foreach ($eligible_products as $product) { if ($free_count <= 0) { break; } // 通过购物车对象精准设置对应项的价格为0 $cart->set_cart_item_price($product['key'], 0); $free_count--; } }
关键修复点
- 替换排序依据:不再依赖未生成的
line_total,提前计算每个购物车项的总价(单价×数量)作为排序字段 - 保存购物车项key:确保后续能精准定位到购物车中的对应项,避免修改全局产品价格
- 添加重复触发防护:防止钩子多次执行导致的价格异常
- 调整触发门槛:原代码判断需至少3件才触发,但买2送1规则只需2件符合条件即可触发,此处修正逻辑
内容的提问来源于stack exchange,提问作者user29407306
相关产品推荐
相关产品推荐

