You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义产品重量因邮政编码变更被覆盖,如何保留已设置的cart_item_data?

问题背景

我们销售高度定制化产品,重量差异极大。目前已通过代码实现添加购物车时设置产品重量,这部分功能正常。但访客在结账页面修改邮政编码时,会触发运费计算刷新,此时产品重量被重置。由于采用基于重量的运费计算方式,导致运费价格错误。需要确保cart_item_data设置完成后不再被刷新。

现有代码

// 重量取自自定义插件,获取的值是正确的
function changeWeight( $cart_item_data, $product_id, $variation_id ) {
    $arrEzfc       = $cart_item_data['ezfc_edit_values'];
    $productWeight = 0;

    foreach ( $arrEzfc as $key => $value ) {
        // 计算表单中'Gesamtgewicht'(总重量)值的ID
        if ( $key === 255 || $key === 280 || $key === 301 || $key === 330 || $key === 366 ) {
            $productWeight            = floatval( str_replace( ',', '.', str_replace( '.', '', $value ) ) );
            $cart_item_data['weight']['new'] = $productWeight;
        }
    }
    return $cart_item_data;
}

add_action( 'woocommerce_before_calculate_totals', 'conditionally_change_tax_class', 10000 );
function conditionally_change_tax_class( $cart ){
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    // WooCommerce 3.2版本及以上修改购物车项属性所需的判断
    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;

    // 遍历特定购物车项
    foreach ( $cart->get_cart() as $cart_item ) {
        // 设置新产品重量
        $cart_item['data']->set_weight($cart_item['weight']['new']);
    }
}

解决方案

1. 绑定购物车添加钩子,确保数据存入会话

首先要把changeWeight函数绑定到woocommerce_add_cart_item_data钩子上,这样添加购物车时自定义重量才能被存入cart_item_data并保留在会话中:

add_filter( 'woocommerce_add_cart_item_data', 'changeWeight', 10, 3 );

2. 修正重量重置逻辑

修改conditionally_change_tax_class函数,移除重复执行的限制(AJAX刷新运费时会多次触发该钩子,限制会导致重量无法重新设置),同时增加自定义重量的存在性检查:

add_action( 'woocommerce_before_calculate_totals', 'conditionally_change_tax_class', 10000 );
function conditionally_change_tax_class( $cart ){
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    // 遍历所有购物车项
    foreach ( $cart->get_cart() as $cart_item ) {
        // 检查是否存在自定义重量数据,存在则设置
        if ( isset( $cart_item['weight']['new'] ) && ! empty( $cart_item['weight']['new'] ) ) {
            $cart_item['data']->set_weight( $cart_item['weight']['new'] );
        }
    }
}

3. 确保会话中数据不丢失

添加woocommerce_get_cart_item_from_session钩子,恢复会话中的自定义重量数据,避免AJAX请求时数据丢失:

add_filter( 'woocommerce_get_cart_item_from_session', 'restore_custom_weight_in_session', 10, 3 );
function restore_custom_weight_in_session( $cart_item, $values, $key ) {
    if ( isset( $values['weight']['new'] ) ) {
        $cart_item['weight']['new'] = $values['weight']['new'];
    }
    return $cart_item;
}

核心原理

每次运费刷新(包括修改邮编触发的AJAX请求)时,woocommerce_before_calculate_totals钩子都会执行。通过从cart_item_data中读取预先保存的自定义重量,重新设置给产品,就能避免系统把重量重置为原始值。同时,通过会话钩子确保自定义数据在AJAX请求中不会丢失。

内容的提问来源于stack exchange,提问作者Fewture

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 09:13:26