WooCommerce 3:编程设置促销价后,购物车及结账页显示原价的解决方法
嘿,这个坑我太熟了!你之前的代码应该只是把促销价写到了产品的元数据里,但WooCommerce的购物车在加载时会重新拉取产品的默认价格计算,所以得专门给购物车加个“补丁”才行。下面给你一步步解决:
核心方案:修改购物车的价格计算逻辑
WooCommerce有个专门的钩子woocommerce_before_calculate_totals,会在购物车计算总价之前触发,刚好适合我们修改单个购物车项的价格。把下面的代码放到你的主题functions.php文件里,或者自定义插件中(别直接改WooCommerce核心文件,不然更新就没了):
add_action('woocommerce_before_calculate_totals', 'sync_custom_sale_price_to_cart', 10, 1); function sync_custom_sale_price_to_cart($cart) { // 避免后台和非AJAX场景下的循环调用 if (is_admin() && !defined('DOING_AJAX')) return; // 遍历购物车里的每一项 foreach ($cart->get_cart() as $cart_item_key => $cart_item) { $product = $cart_item['data']; // 这里替换成你之前存储促销价的meta键名,比如你之前用的是_custom_sale_price $custom_sale_price = get_post_meta($product->get_id(), '_custom_sale_price', true); // 确保促销价存在且是数字 if (!empty($custom_sale_price) && is_numeric($custom_sale_price)) { // 设置购物车项的实际结算价格 $product->set_price($custom_sale_price); // 同步设置促销价和原价,这样购物车会显示“划掉原价+促销价”的样式 $product->set_regular_price($product->get_regular_price()); $product->set_sale_price($custom_sale_price); } } }
关键细节说明
- 避免循环调用:代码里的
is_admin() && !defined('DOING_AJAX')判断是为了防止后台操作时触发重复计算,导致报错。 - meta键名对应:一定要把
_custom_sale_price改成你之前设置促销价时用的实际键名,比如如果之前用update_post_meta($product_id, '_sale_price', $price),那这里就用_sale_price。 - 价格样式同步:如果想要购物车显示“原价划掉+促销价”的标准样式,就必须同时设置
set_regular_price和set_sale_price,不然只会显示单一价格。
额外优化:针对特定条件的促销价
如果你的促销价是针对特定用户(比如会员)、特定时间或者其他条件的,可以在代码里加上判断逻辑。比如针对会员用户的促销:
add_action('woocommerce_before_calculate_totals', 'set_member_sale_price_in_cart', 10, 1); function set_member_sale_price_in_cart($cart) { if (is_admin() && !defined('DOING_AJAX')) return; // 只给会员用户应用促销价 if (!current_user_can('customer')) return; foreach ($cart->get_cart() as $cart_item_key => $cart_item) { $product = $cart_item['data']; $member_sale_price = get_post_meta($product->get_id(), '_member_sale_price', true); if ($member_sale_price) { $product->set_price($member_sale_price); $product->set_sale_price($member_sale_price); $product->set_regular_price($product->get_regular_price()); } } }
最后检查点
如果之前你设置促销价时同时加了时间限制(比如_sale_price_dates_from和_sale_price_dates_to),记得清空这两个元数据,不然WooCommerce会优先判断时间是否在促销期内,导致自定义价格不生效:
// 清空促销时间限制,确保永久生效 update_post_meta($product_id, '_sale_price_dates_from', ''); update_post_meta($product_id, '_sale_price_dates_to', '');
内容的提问来源于stack exchange,提问作者Marcus Christiansen
相关产品推荐
相关产品推荐

