WooCommerce批量动态定价对接ACF及多档位折扣代码调整问题
ACF字段取值失效原因
- 上下文不匹配:
get_field()函数默认读取当前全局页面的自定义字段,在购物车计算逻辑中,全局上下文不是对应的商品,必须传入商品ID作为第二个参数才能读取指定商品的ACF值,正确调用格式为get_field('字段别名', $cart_item['product_id']) - 缺少空值兜底:如果商品未填写对应档位的字段值,
get_field()会返回空值,导致阈值、折扣变量为无效值,规则无法正常匹配 - 字段类型错误:如果ACF字段配置的返回类型不是纯数字,也会导致数值比较、价格计算失效,需将对应ACF字段的类型设置为「数字」
5档折扣优化方案
使用switch语句不会带来明显的性能优势,反而会让代码冗余,更推荐用规则数组动态匹配,后续增减档位仅需调整ACF字段配置即可,不需要修改核心逻辑:
- 先在ACF后台给商品(product)post type 新增10个数字类型字段:
- 阈值字段别名:
discount_threshold_1、discount_threshold_2、discount_threshold_3、discount_threshold_4、discount_threshold_5 - 折扣字段别名:
discount_value_1、discount_value_2、discount_value_3、discount_value_4、discount_value_5
- 阈值字段别名:
- 替换原有代码为以下版本:
/** * @snippet 5档动态批量定价 - WooCommerce + ACF * @compatible WooCommerce 3.8及以上 */ add_action( 'woocommerce_before_calculate_totals', 'bbloomer_quantity_based_pricing', 9999 ); function bbloomer_quantity_based_pricing( $cart ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return; foreach ( $cart->get_cart() as $cart_item ) { $product_id = $cart_item['product_id']; $quantity = $cart_item['quantity']; $rules = []; // 读取5档配置,过滤空值 for ($i = 1; $i <=5; $i++) { $threshold = get_field("discount_threshold_{$i}", $product_id); $discount = get_field("discount_value_{$i}", $product_id); if (is_numeric($threshold) && is_numeric($discount) && $threshold > 0 && $discount >=0) { $rules[] = [ 'threshold' => $threshold, 'discount' => $discount ]; } } // 没有配置规则就跳过 if (empty($rules)) continue; // 按阈值从小到大排序 usort($rules, function($a, $b) { return $a['threshold'] - $b['threshold']; }); // 匹配最高满足的档位 $matched_discount = 0; foreach (array_reverse($rules) as $rule) { if ($quantity >= $rule['threshold']) { $matched_discount = $rule['discount']; break; } } // 应用折扣 if ($matched_discount > 0) { $final_price = round( $cart_item['data']->get_price() - $matched_discount, 2 ); $cart_item['data']->set_price( $final_price ); } } }
以上代码会自动读取每个商品独立配置的档位规则,过滤掉未填写的无效档位,自动匹配用户购买数量对应的最高档位折扣,不需要硬编码任何固定规则。
内容的提问来源于stack exchange,提问作者Andy Garard
相关产品推荐
相关产品推荐

