WooCommerce按用户角色分级折扣排除指定分类失效问题
修复WooCommerce分类排除失效的分级折扣代码
问题根源
原代码的分类排除功能失效,主要因为以下两点:
- 处理产品变体时,错误使用了变体ID而非父产品ID获取分类信息
- 未对分类术语的获取结果做有效性检查,可能因无分类或错误导致逻辑中断
修正后的完整代码
add_action( 'woocommerce_cart_calculate_fees', 'custom_discount_based_on_cart_total', 10, 1 ); function custom_discount_based_on_cart_total( $cart ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; // 排除的分类slug $excluded_categories = array( 'redshirt1', 'redshirt2', 'redshirt3', 'redshirt4' ); $discounted_total = 0; foreach ( $cart->get_cart() as $cart_item ) { // 使用父产品ID(兼容变体商品) $product_id = $cart_item['product_id']; $terms = get_the_terms( $product_id, 'product_cat' ); // 跳过无分类或获取分类失败的情况 if ( ! $terms || is_wp_error( $terms ) ) { $discounted_total += $cart_item['line_subtotal']; continue; } $exclude = false; foreach ( $terms as $term ) { if ( in_array( $term->slug, $excluded_categories ) ) { $exclude = true; break; } } if ( ! $exclude ) { $discounted_total += $cart_item['line_subtotal']; } } $discount = 0; $discount_text = ""; // 判断是否为VIP用户 $user = wp_get_current_user(); $is_vip = in_array( 'vip', (array) $user->roles ); if ( $discounted_total >= 2000 && $discounted_total < 4000 ) { $discount = $discounted_total * ($is_vip ? 0.03 : 0.02); $discount_text = '折扣 ' . ($is_vip ? '3%' : '2%'); } else if ( $discounted_total >= 4000 && $discounted_total < 6000 ) { $discount = $discounted_total * ($is_vip ? 0.05 : 0.04); $discount_text = '折扣 ' . ($is_vip ? '5%' : '4%'); } else if ( $discounted_total >= 6000 ) { $discount = $discounted_total * ($is_vip ? 0.07 : 0.06); $discount_text = '折扣 ' . ($is_vip ? '7%' : '6%'); } if ( $discount > 0 ) { $cart->add_fee( __( $discount_text, 'woocommerce' ), -$discount ); } } add_action( 'woocommerce_before_cart', 'show_discount_message' ); function show_discount_message() { $cart = WC()->cart; $excluded_categories = array( 'redshirt1', 'redshirt2', 'redshirt3', 'redshirt4' ); $discounted_total = 0; // 统一使用与折扣计算相同的逻辑计算符合条件的金额 foreach ( $cart->get_cart() as $cart_item ) { $product_id = $cart_item['product_id']; $product_cats = wp_get_post_terms( $product_id, 'product_cat' ); if ( ! $product_cats || is_wp_error( $product_cats ) ) { $discounted_total += $cart_item['line_subtotal']; continue; } $exclude = false; foreach ( $product_cats as $product_cat ) { if ( in_array( $product_cat->slug, $excluded_categories ) ) { $exclude = true; break; } } if ( ! $exclude ) { $discounted_total += $cart_item['line_subtotal']; } } $user = wp_get_current_user(); $is_vip = in_array( 'vip', (array) $user->roles ); $return_to = wc_get_page_permalink( 'shop' ); if ( $discounted_total < 2000 ) { $difference = 2000 - $discounted_total; $added_text = '再消费 ' . wc_price( $difference ) . ' 即可享受' . ($is_vip ? '3%' : '2%') . '折扣!'; $notice = sprintf( '<a href="%s" class="button wc-forward">%s</a> %s', esc_url( $return_to ), '继续购物', $added_text ); wc_print_notice( $notice, 'notice' ); } else if ( $discounted_total >= 2000 && $discounted_total < 4000 ) { $difference = 4000 - $discounted_total; $added_text = '再消费 ' . wc_price( $difference ) . ' 即可升级至' . ($is_vip ? '5%' : '4%') . '折扣!'; $notice = sprintf( '<a href="%s" class="button wc-forward">%s</a> %s', esc_url( $return_to ), '继续购物', $added_text ); wc_print_notice( $notice, 'notice' ); } else if ( $discounted_total >= 4000 && $discounted_total < 6000 ) { $difference = 6000 - $discounted_total; $added_text = '再消费 ' . wc_price( $difference ) . ' 即可升级至' . ($is_vip ? '7%' : '6%') . '折扣!'; $notice = sprintf( '<a href="%s" class="button wc-forward">%s</a> %s', esc_url( $return_to ), '继续购物', $added_text ); wc_print_notice( $notice, 'notice' ); } }
核心修复说明
- 兼容产品变体:使用
$cart_item['product_id']替代$product->get_id(),确保始终获取父产品的分类信息 - 增加有效性检查:对
get_the_terms和wp_get_post_terms的返回值做判断,避免因无分类或错误导致的逻辑异常 - 逻辑一致性:统一折扣计算和提示信息中的金额统计逻辑,避免两个功能出现数据不一致的情况
- 变量命名优化:将
$is_customer改为$is_vip,更贴合业务语义
内容的提问来源于stack exchange,提问作者Boggie
相关产品推荐
相关产品推荐

