自定义产品重量因邮政编码变更被覆盖,如何保留已设置的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
相关产品推荐
相关产品推荐

