购物车含分类A商品时为分类B商品打9折的功能故障排查
购物车分类折扣不生效问题排查与修复
问题描述
我需要实现:当购物车中有分类A的商品时,给所有分类B的商品打10%折扣(支持按总金额折扣或单品分别折扣)。但我编写的代码未生效,请求排查问题:
add_action( 'woocommerce_before_calculate_totals', 'apply_category_discount_in_cart', 10, 1 ); function apply_category_discount_in_cart( $cart ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return; $discount_amount = 0; $category_A_in_cart = false; // Loop through each item in the cart foreach ( $cart->get_cart() as $cart_item ) { $product = $cart_item['data']; // Check if the product has category A if ( has_term( 'categorya', 'product_cat', $product->get_id() ) ) { $category_A_in_cart = true; break; } } // If a product with category A is found in the cart if ( $category_A_in_cart ) { // Loop through each item in the cart again foreach ( $cart->get_cart() as $cart_item ) { $product = $cart_item['data']; // Check if the product has category B if ( has_term( 'categoryb', 'product_cat', $product->get_id() ) ) { $discount_amount += $cart_item['line_total'] * 0.1; $cart_item['data']->set_price( $cart_item['data']->get_price() * 0.9 ); } } // Add the discount amount as a fee $cart->add_fee( 'Discount', -$discount_amount, true ); } }
问题根源分析
- 重复折扣逻辑冲突:你同时执行了单品降价和添加负费用折扣两种操作,导致计算逻辑混乱,且
line_total在woocommerce_before_calculate_totals钩子执行阶段还未完成最终计算,直接取值会得到错误结果。 - 分类检查对象错误:使用
$product->get_id()获取ID时,若商品是可变产品(带属性的商品),该ID是子产品ID,而分类通常设置在父产品上,应该用$cart_item['product_id']来检查分类归属。 - 价格修改可靠性不足:直接修改
$cart_item['data']->get_price()的方式,在部分场景下会因对象引用问题导致修改不生效。
修复方案
方案1:单品分别折扣(直接修改商品单价)
add_action( 'woocommerce_before_calculate_totals', 'apply_category_discount_in_cart', 20, 1 ); function apply_category_discount_in_cart( $cart ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return; $category_a_exists = false; $category_a_slug = 'categorya'; // 替换为你的分类A别名 $category_b_slug = 'categoryb'; // 替换为你的分类B别名 // 检查购物车是否存在分类A商品 foreach ( $cart->get_cart() as $cart_item ) { if ( has_term( $category_a_slug, 'product_cat', $cart_item['product_id'] ) ) { $category_a_exists = true; break; } } if ( $category_a_exists ) { // 为分类B商品设置10%折扣 foreach ( $cart->get_cart() as $cart_item ) { if ( has_term( $category_b_slug, 'product_cat', $cart_item['product_id'] ) ) { $original_price = $cart_item['data']->get_regular_price(); $discounted_price = $original_price * 0.9; $cart_item['data']->set_price( $discounted_price ); } } } }
- 说明:该方案直接修改分类B商品的单价,购物车中每个单品会显示折扣后价格,总价自动计算。
方案2:总金额折扣(通过负费用实现)
add_action( 'woocommerce_cart_calculate_fees', 'apply_category_b_total_discount', 10, 1 ); function apply_category_b_total_discount( $cart ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; $category_a_slug = 'categorya'; $category_b_slug = 'categoryb'; $discount_rate = 0.1; $category_a_exists = false; $category_b_total = 0; // 检查分类A商品是否存在 foreach ( $cart->get_cart() as $cart_item ) { if ( has_term( $category_a_slug, 'product_cat', $cart_item['product_id'] ) ) { $category_a_exists = true; break; } } if ( $category_a_exists ) { // 计算分类B商品的总金额 foreach ( $cart->get_cart() as $cart_item ) { if ( has_term( $category_b_slug, 'product_cat', $cart_item['product_id'] ) ) { $category_b_total += $cart_item['line_total']; } } // 添加折扣费用项 if ( $category_b_total > 0 ) { $discount_amount = $category_b_total * $discount_rate; $cart->add_fee( '分类B专属折扣', -$discount_amount, true ); } } }
- 说明:该方案不修改单品价格,而是在购物车底部添加一个负费用项,显示分类B商品的总折扣金额。
内容的提问来源于stack exchange,提问作者Richard Mišenčík
相关产品推荐
相关产品推荐

