Woocommerce:如何在发送完成订单邮件前保存ACF字段避免重复更新?
解决Woocommerce订单切换至已完成时自动保存ACF自定义字段的问题
你的原代码无法生效的核心问题有两个:
- 函数内使用了未定义的变量
$post_ID、$post、$update,会触发PHP报错导致逻辑中断 - 直接调用
save_post钩子不是针对Woocommerce订单的正确保存方式,订单作为shop_order类型的自定义帖子,需要结合ACF的API或元数据更新方法处理
以下是两种可行的解决方案:
方案1:状态变更时针对性保存指定ACF字段
适用于你只需要保存单个或少数几个ACF字段的场景,直接在订单状态切换为已完成时,从POST请求中获取字段值并更新:
add_action('woocommerce_order_status_changed', 'save_acf_fields_on_order_completed', 10, 4); function save_acf_fields_on_order_completed($order_id, $old_status, $new_status, $order) { // 仅在状态变为已完成时执行 if ($new_status !== 'completed') return; // 替换为你的ACF字段键(在ACF字段编辑页面可查看) $target_field_key = 'custom_order_note'; if (isset($_POST['acf'][$target_field_key])) { // 根据字段类型做内容清理,文本类型用sanitize_text_field即可 $clean_value = sanitize_text_field($_POST['acf'][$target_field_key]); // 使用ACF官方函数更新字段 update_field($target_field_key, $clean_value, $order_id); } }
方案2:订单保存时批量保存所有ACF字段
适用于需要保存多个ACF字段的场景,利用订单保存的钩子,确保字段和订单状态同步更新:
add_action('woocommerce_process_shop_order_meta', 'save_acf_fields_with_order_status', 10, 2); function save_acf_fields_with_order_status($order_id, $post) { $order = wc_get_order($order_id); $current_status = $order->get_status(); // 仅在订单状态设为已完成时执行 if ($current_status !== 'completed') return; // 批量处理POST中的所有ACF字段 if (isset($_POST['acf'])) { foreach ($_POST['acf'] as $field_key => $value) { // 根据字段类型调整清理规则,例如富文本用wp_kses_post if (is_string($value)) { $value = sanitize_text_field($value); } elseif (is_array($value)) { $value = array_map('sanitize_text_field', $value); } update_field($field_key, $value, $order_id); } } }
注意事项
- 必须替换代码中的
custom_order_note为你实际使用的ACF字段键 - 如果是复杂类型字段(如图片、多选框),需要调整内容清理的逻辑,避免数据丢失或被错误过滤
- 测试前建议开启WP_DEBUG模式,排查是否有语法或逻辑报错
内容的提问来源于stack exchange,提问作者LBF
相关产品推荐
相关产品推荐

