
本文介绍如何通过 acf 自定义字段(如多选复选框)控制购物车与结算页中仅显示匹配的 woocommerce 配送方式,例如当产品标记为“cp”时,仅启用“Čp”配送方法。
本文介绍如何通过 acf 自定义字段(如多选复选框)控制购物车与结算页中仅显示匹配的 woocommerce 配送方式,例如当产品标记为“cp”时,仅启用“Čp”配送方法。
在 WooCommerce 中实现「按产品属性动态过滤配送方式」是一个常见但易出错的需求。核心逻辑是:遍历当前购物包(package)中的所有商品,检查其 ACF 字段值(如 zpusob_prepravy),汇总所需启用的配送标识(如 'cp', 'ppl', 'dpd'),再据此保留或移除对应 ID 的配送方法。
⚠️ 原代码存在多个关键问题:
- 未遍历 $package['contents'],直接调用 get_field('zpusob_prepravy') 会返回空或默认值(因无上下文产品 ID);
- $shipping_id 变量未定义,且硬编码了错误的费率 ID(如 'flat_rate:1' 或 'table_rate_shipping_first-class');
- 未正确映射 ACF 值('cp')到实际的 WooCommerce 配送方法 ID(如 'flat_rate:2' 对应 ČP);
- 缺少对多商品混合场景的兼容处理(例如购物车含 CP 和 DPD 商品时,应同时显示两者)。
✅ 正确实现步骤如下:
1. 明确配送方法 ID
进入 WooCommerce → 设置 → 配送 → 配送区域 → 编辑对应区域 → 配送方法,鼠标悬停在方法名称上,查看浏览器状态栏或检查元素,获取真实 ID 格式(通常为 flat_rate:ID、local_pickup:0 等)。例如:
- ČP → flat_rate:2
- PPL → flat_rate:3
- DPD → flat_rate:4
2. 编写健壮的过滤函数
将以下代码添加至主题 functions.php 或子主题中:
add_filter( 'woocommerce_package_rates', 'filter_shipping_methods_by_acf_field', 10, 2 );
function filter_shipping_methods_by_acf_field( $rates, $package ) {
// 初始化允许的配送标识集合
$allowed_methods = array();
// 遍历当前包裹内所有商品
foreach ( $package['contents'] as $item_id => $item ) {
$product = $item['data'];
$product_id = $product->get_id();
// 获取该商品的 ACF 复选框字段值(返回数组,如 ['cp', 'dpd'])
$shipping_options = get_field( 'zpusob_prepravy', $product_id );
// 若字段存在且为数组,则合并到允许列表
if ( is_array( $shipping_options ) ) {
$allowed_methods = array_merge( $allowed_methods, $shipping_options );
}
}
// 去重并确保小写一致性
$allowed_methods = array_unique( array_map( 'strtolower', $allowed_methods ) );
// 定义 ACF 值到 WooCommerce 配送 ID 的映射关系(请按实际 ID 修改!)
$method_mapping = array(
'cp' => 'flat_rate:2', // ČP 配送
'ppl' => 'flat_rate:3', // PPL 配送
'dpd' => 'flat_rate:4', // DPD 配送
);
// 构建需保留的配送 ID 列表
$keep_ids = array();
foreach ( $allowed_methods as $option ) {
if ( isset( $method_mapping[ $option ] ) ) {
$keep_ids[] = $method_mapping[ $option ];
}
}
// 移除非许可的配送方法
foreach ( $rates as $rate_id => $rate ) {
if ( ! in_array( $rate_id, $keep_ids ) ) {
unset( $rates[ $rate_id ] );
}
}
return $rates;
}
3. 注意事项与调试建议
- ✅ 必须传入 $product_id:get_field() 第二个参数不可省略,否则无法获取指定商品的字段值;
- ✅ 支持多商品混合场景:函数自动聚合所有商品的选项,确保购物车含 CP + DPD 商品时,两种配送均可见;
- ⚠️ ID 必须精确匹配:请务必通过后台确认每个配送方法的真实 ID,大小写和冒号缺一不可;
- ? 调试技巧:临时添加 error_log( print_r( $allowed_methods, true ) ); 查看实际读取到的字段值;
- ? 避免缓存干扰:启用对象缓存或页面缓存插件时,请清空缓存后再测试;
- ? 扩展性提示:如需排除某方法(如禁用所有非匹配项),可改用 array_intersect_key() 替代循环 unset。
此方案兼顾准确性、可维护性与 WooCommerce 最佳实践,适用于生产环境。完成配置后,用户在结算页将仅看到与所购商品 ACF 字段严格匹配的配送选项,提升转化率与用户体验。










