仅更新WooCommerce购物车/结账页面小计的正确Hook咨询
解决WooCommerce中只想修改小计而非产品价格的问题
嘿,我明白你的需求了——你现在的代码会直接修改产品本身的价格,但你希望保持产品价格显示不变,只把自定义字段的金额加到小计里对吧?之前尝试woocommerce_cart_product_subtotal没用,是因为这个钩子只负责修改显示的文本,不会影响实际的订单金额计算,所以必须同时处理显示和实际金额逻辑两部分才行。
问题分析
你原来的代码是通过set_price()修改了产品的基础价格,这会导致购物车中显示的产品价格变成「原价格+自定义字段值」,但你想要的是:比如变体价格49美元,自定义复选框价格79美元,购物车显示产品价格49美元,小计直接变成49+79=128美元(或按数量累加),同时结账金额也正确包含这笔费用。
解决方案
下面给你两种可行的方案,根据你的实际需求选择:
方案1:给每个购物车项添加单独的自定义费用(推荐)
这个方案会在购物车中添加一个清晰的自定义费用项,同时保持产品价格不变,订单总价也会正确计算:
// 计算并添加自定义费用到订单总价 function add_custom_item_fee( $cart ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; $total_custom_fee = 0; // 遍历每个购物车项 foreach ( $cart->get_cart() as $cart_item ) { // 获取自定义字段的值 $custom_fee = get_post_meta( $cart_item['product_id'], '_number_field_1', true ); $custom_fee = floatval( $custom_fee ); if ( $custom_fee > 0 ) { // 如果是每个商品都加一次费用,就乘以数量;如果是每个购物车项只加一次,去掉* $cart_item['quantity'] $total_custom_fee += $custom_fee * $cart_item['quantity']; } } // 添加总自定义费用到购物车 if ( $total_custom_fee > 0 ) { $cart->add_fee( '自定义选项费用', $total_custom_fee, true, '' ); } } add_action( 'woocommerce_before_calculate_totals', 'add_custom_item_fee', 99 ); // 修改购物车项的小计显示,把自定义费用合并到小计里(可选,如果你想让小计直接显示总和) function show_combined_subtotal( $subtotal, $product, $cart_item, $cart_item_key ) { $custom_fee = get_post_meta( $cart_item['product_id'], '_number_field_1', true ); $custom_fee = floatval( $custom_fee ); if ( $custom_fee > 0 ) { // 计算合并后的小计:(原价格 + 自定义费用) × 数量 $combined_subtotal = ( $product->get_price() + $custom_fee ) * $cart_item['quantity']; $subtotal = wc_price( $combined_subtotal ); } return $subtotal; } add_filter( 'woocommerce_cart_product_subtotal', 'show_combined_subtotal', 10, 4 ); // 可选:修改购物车中产品价格的显示,标注自定义费用 function display_price_with_custom_fee( $price, $cart_item ) { $custom_fee = get_post_meta( $cart_item['product_id'], '_number_field_1', true ); $custom_fee = floatval( $custom_fee ); if ( $custom_fee > 0 ) { $original_price = wc_price( $cart_item['data']->get_price() ); $fee_display = wc_price( $custom_fee ); $price = "$original_price + $fee_display"; } return $price; } add_filter( 'woocommerce_cart_item_price', 'display_price_with_custom_fee', 10, 2 );
方案2:直接修改购物车项的小计计算(不显示单独费用项)
如果你不想显示单独的费用项,只想默默把自定义费用加到小计里,可以用这个方案:
function adjust_cart_item_subtotal( $cart ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) { $custom_fee = get_post_meta( $cart_item['product_id'], '_number_field_1', true ); $custom_fee = floatval( $custom_fee ); if ( $custom_fee > 0 ) { // 获取原产品价格 $original_price = $cart_item['data']->get_price(); // 设置新的价格为原价格+自定义费用(这样小计会自动变成新价格×数量) // 但我们用一个临时元数据保存原价格,用来在显示时还原 $cart_item['data']->set_price( $original_price + $custom_fee ); $cart_item['data']->add_meta_data( '_original_price', $original_price, true ); } } } add_action( 'woocommerce_before_calculate_totals', 'adjust_cart_item_subtotal', 99 ); // 还原购物车页面显示的产品价格为原价格 function restore_original_price_display( $price, $cart_item ) { if ( $cart_item['data']->get_meta( '_original_price' ) ) { $original_price = $cart_item['data']->get_meta( '_original_price' ); $price = wc_price( $original_price ); } return $price; } add_filter( 'woocommerce_cart_item_price', 'restore_original_price_display', 10, 2 );
为什么之前的尝试无效?
woocommerce_cart_product_subtotal这个钩子只是用来修改前端显示的小计文本,不会改变WooCommerce内部计算订单总价的逻辑,所以即使你修改了显示的数值,实际结账金额还是原来的,这就是你觉得无效的原因。必须通过woocommerce_before_calculate_totals钩子来修改实际的金额计算,才能让结账金额正确。
内容的提问来源于stack exchange,提问作者beginner115
相关产品推荐
相关产品推荐

