WooCommerce:为特定用户角色基于产品自定义字段设置并显示折扣
解决方案:针对Clubmember角色显示自定义折扣价与原价
实现思路
要同时满足三个核心需求:
- 仅对
clubmember角色用户生效 - 读取产品自定义字段
clubmember_price的折扣百分比计算实际售价 - 在产品页、购物车、结账页同时展示原价和折扣价
需要结合WooCommerce的价格过滤钩子与显示控制钩子,既修改实际结算价格,又保留原价的显示逻辑,让用户能直观看到优惠对比。
完整代码实现
// 1. 为Clubmember角色计算自定义折扣价(保留原价用于显示) add_filter('woocommerce_product_get_price', 'clubmember_custom_price', 10, 2); add_filter('woocommerce_product_variation_get_price', 'clubmember_custom_price', 10, 2); add_filter('woocommerce_product_get_regular_price', 'clubmember_custom_price', 10, 2); add_filter('woocommerce_product_variation_get_regular_price', 'clubmember_custom_price', 10, 2); function clubmember_custom_price($price, $product) { // 仅对clubmember角色且产品有有效折扣字段的情况生效 if (!current_user_can('clubmember') || !$discount_percent = $product->get_meta('clubmember_price')) { return $price; } // 校验折扣百分比的有效性 $discount_percent = absint($discount_percent); if ($discount_percent < 1 || $discount_percent > 99) { return $price; } // 基于原价计算折扣价,保留原价字段用于显示对比 $original_price = $product->get_regular_price() ?: $price; return round($original_price * (100 - $discount_percent) / 100, wc_get_price_decimals()); } // 2. 强制在产品页显示原价与折扣价对比 add_filter('woocommerce_show_sale_price', '__return_true'); add_filter('woocommerce_product_is_on_sale', 'clubmember_force_sale_badge', 10, 2); function clubmember_force_sale_badge($is_sale, $product) { if (current_user_can('clubmember') && $product->get_meta('clubmember_price')) { return true; } return $is_sale; } // 3. 在购物车/结账页显示原价与折扣价对比 add_filter('woocommerce_cart_item_price', 'clubmember_cart_price_display', 10, 3); add_filter('woocommerce_cart_item_subtotal', 'clubmember_cart_price_display', 10, 3); function clubmember_cart_price_display($display_price, $cart_item, $cart_item_key) { if (!current_user_can('clubmember')) { return $display_price; } $product = $cart_item['data']; $discount_percent = $product->get_meta('clubmember_price'); if (!$discount_percent) { return $display_price; } $original_price = wc_get_price_to_display($product, array('price' => $product->get_regular_price() ?: $product->get_price())); $discounted_price = wc_get_price_to_display($product); // 调用WooCommerce原生函数生成规范的价格对比格式 return wc_format_sale_price($original_price, $discounted_price); }
代码原理拆解
1. 价格计算逻辑
- 使用
woocommerce_product_get_price等系列钩子,为目标角色计算专属折扣价,但不修改产品原始原价字段,让WooCommerce原生的价格显示逻辑能识别出“原价”与“折扣价”的差异。 - 先校验用户角色和自定义字段的有效性,避免非目标用户触发逻辑错误。
- 用
wc_get_price_decimals()保证价格小数位数与商店全局设置一致。
2. 产品页显示控制
- 通过
woocommerce_show_sale_price强制显示销售价格,woocommerce_product_is_on_sale让产品自动带上促销标识(不需要可移除该钩子)。 - 复用WooCommerce原生的销售价格显示模板,自动生成“原价划掉+折扣价”的样式,无需手写HTML。
3. 购物车/结账页显示
- 重写
woocommerce_cart_item_price和woocommerce_cart_item_subtotal钩子,替换默认价格显示,添加原价对比。 - 使用
wc_format_sale_price()调用内置格式化函数,确保显示样式与商店全局设置统一。
注意事项
- 产品自定义字段
clubmember_price仅需填写纯数字(如10代表10%折扣)。 - 若使用缓存插件,需针对用户角色做缓存隔离,避免不同角色看到相同价格。
- 代码已兼容变量产品(Variation),可直接测试多规格产品的显示效果。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

