woocommerce_package_rates过滤后配送方式选择异常求助:默认未选中+购物车选后失效
WooCommerce配送方式过滤函数的默认选中问题修复
你的代码实现了「有免费配送时禁用付费配送」的核心功能,但出现的两个问题本质是修改配送方式数组时破坏了WooCommerce依赖的键名和选中状态标记,以下是针对性的修复方案:
问题根源
- 你用
array_unshift()和[]添加配送方式时,会重置数组的数字索引,而WooCommerce是通过配送方式的id(作为数组键名)来跟踪选中状态的,索引丢失后系统无法匹配之前选中的选项。 - 新添加的配送方式(比如修改后的fermopoint)没有继承或设置
selected属性,导致页面加载时没有默认选中项。
修复后的完整代码
add_filter( 'woocommerce_package_rates', 'disable_paid_shipping', 9999, 2 ); function disable_paid_shipping( $rates, $package ) { $free_rates = array(); $selected_rate_id = ''; // 先记录原本选中的配送方式ID foreach ( $rates as $rate_id => $rate ) { if ( $rate->selected ) { $selected_rate_id = $rate_id; } // 收集原有免费配送方式,保留原键名 if ( str_contains( $rate->label, "gratuita" ) || str_contains( $rate->label, "gratuito" ) ) { $free_rates[$rate_id] = $rate; } } // 处理fermopoint并加入免费列表(保留原键名) if ( isset( $rates['fermopoint'] ) ) { $fermopoint = $rates['fermopoint']; $fermopoint->cost = 0; $fermopoint->label .= ' gratuito'; // 保留原键名,确保系统能识别 $free_rates[$fermopoint->id] = $fermopoint; } // 处理local并加入免费列表(保留原键名) if ( isset( $rates['local'] ) ) { $free_rates[$rates['local']->id] = $rates['local']; } if ( !empty( $free_rates ) ) { // 确保有默认选中项:优先保留原本选中的(如果它在免费列表里),否则选第一个 $has_selected = false; foreach ( $free_rates as $rate_id => $rate ) { if ( $rate_id === $selected_rate_id ) { $rate->selected = true; $has_selected = true; break; } } if ( !$has_selected ) { reset( $free_rates ); $first_rate_id = key( $free_rates ); $free_rates[$first_rate_id]->selected = true; } $rates = $free_rates; } return $rates; }
关键改动说明
- 保留原数组键名:所有加入
$free_rates的配送方式都使用原rate->id作为键名,WooCommerce能通过键名匹配选中状态,避免购物车AJAX刷新后选中状态丢失。 - 跟踪并恢复选中状态:先记录原本选中的配送方式ID,如果它在免费列表里就保持选中;如果没有,自动选中第一个免费配送方式,解决默认不选中的问题。
- 避免索引重置:不再使用
array_unshift()这类会重置索引的函数,直接通过键名添加元素,保持数组结构的一致性。
额外注意事项
- 确保
fermopoint和local的ID匹配你实际的配送方式ID,代码里的$rates['fermopoint']需要对应后台配置的配送方式ID。 - 测试前请清空WooCommerce缓存(WooCommerce > 状态 > 工具 > 清除配送缓存),避免旧的配送方式数据干扰。
内容的提问来源于stack exchange,提问作者checkm
相关产品推荐
相关产品推荐

