
本文详解如何在 WordPress REST API 创建文章时,正确提交并保存 ACF 字段值——关键在于理解 ACF 字段不支持直接通过 wp/v2 端点的 acf_fields 参数写入,需结合 acf/save_post 钩子与 update_field() 函数实现。
本文详解如何在 wordpress rest api 创建文章时,正确提交并保存 acf 字段值——关键在于理解 acf 字段不支持直接通过 `wp/v2` 端点的 `acf_fields` 参数写入,需结合 `acf/save_post` 钩子与 `update_field()` 函数实现。
在 WordPress 中使用 Advanced Custom Fields(ACF)插件时,开发者常误以为可通过 REST API 的 POST /wp/v2/{post_type} 请求体中直接嵌套 acf_fields 或 fields 对象来批量设置 ACF 值。但事实是:WordPress 原生 REST API 默认不处理 ACF 字段的写入逻辑,即使你注册了自定义文章类型并启用了 show_in_rest => true,ACF 字段也不会自动映射或保存。
你的 JavaScript 代码中使用 acf_fields: { ... } 是无效的——该键名并非 REST API 接受的标准参数,且 ACF 插件未为此提供默认解析器。因此,尽管文章成功创建(标题、内容、状态正常),ACF 字段却始终为空。
✅ 正确方案:采用「分离式提交 + 服务端钩子填充」策略:
- 前端仅提交基础字段(如 title, content, status, post_type),并可附带自定义数据(如经纬度)作为临时载体;
- 后端监听 acf/save_post 钩子(推荐),在文章保存完成后,调用 update_field() 安全写入 ACF 值。
以下是完整实现步骤:
安全的随机密码生成器。支持自定义长度、字符类型(大写/小写字母、数字、特殊符号),排除相似字符,批量生成。纯 Python 标准库,无需 API 密钥。
✅ 步骤一:修正前端 AJAX 请求(移除无效 acf_fields)
createMarker(latitude, longitude) {
const ourNewPost = {
title: `${latitude}, ${longitude}`,
content: `Coordinates: ${latitude}, ${longitude}`,
status: "publish",
// 关键:将 ACF 所需数据作为自定义字段传入(需提前注册为可写入的 REST 字段)
points_latitude: latitude.toString(),
points_longitude: longitude.toString(),
points_title: "test"
};
$.ajax({
beforeSend: (xhr) => {
xhr.setRequestHeader("X-WP-Nonce", myData.nonce);
},
url: myData.root_url + "/wp-json/wp/v2/points/",
type: "POST",
data: ourNewPost,
success: (response) => {
console.log("Post created with ID:", response.id);
},
error: (xhr) => {
console.error("Error:", xhr.responseJSON?.message || xhr.statusText);
}
});
}
⚠️ 注意:若需在 REST 请求中直接传递自定义字段(如 points_latitude),必须先在 PHP 中显式注册这些字段为可写入的 REST 参数:
// functions.php 或插件文件中
function register_points_rest_fields() {
register_rest_field('points', 'points_latitude', [
'schema' => ['type' => 'string'],
'get_callback' => null,
'update_callback' => function($value, $post, $field_name) {
update_field($field_name, $value, $post->ID);
}
]);
register_rest_field('points', 'points_longitude', [
'schema' => ['type' => 'string'],
'get_callback' => null,
'update_callback' => function($value, $post, $field_name) {
update_field($field_name, $value, $post->ID);
}
]);
register_rest_field('points', 'points_title', [
'schema' => ['type' => 'string'],
'get_callback' => null,
'update_callback' => function($value, $post, $field_name) {
update_field($field_name, $value, $post->ID);
}
]);
}
add_action('rest_api_init', 'register_points_rest_fields');
✅ 步骤二:服务端使用 acf/save_post 钩子统一处理(更推荐)
若不想逐个注册 REST 字段,或需复杂逻辑(如根据其他字段计算 ACF 值),请采用此方式:
// 在主题 functions.php 或插件中添加
add_action('acf/save_post', 'save_points_acf_fields', 10, 1);
function save_points_acf_fields($post_id) {
// 确保仅处理 'points' 自定义文章类型,且非自动保存/预览
if (wp_is_post_revision($post_id) || wp_is_post_autosave($post_id)) {
return;
}
if (get_post_type($post_id) !== 'points') {
return;
}
// 从 $_POST 或请求体中提取原始数据(需确保 nonce 已验证)
// 注意:此处需配合前端发送额外参数,或通过其他方式传递(如 post_meta 临时存储)
// 更健壮做法:在 createMarker 中添加一个隐藏字段标识来源,并用 $_POST 获取
if (isset($_POST['points_latitude']) && isset($_POST['points_longitude'])) {
$lat = sanitize_text_field($_POST['points_latitude']);
$lng = sanitize_text_field($_POST['points_longitude']);
$title = sanitize_text_field($_POST['points_title'] ?? 'Default Title');
update_field('points_latitude', $lat, $post_id);
update_field('points_longitude', $lng, $post_id);
update_field('points_title', $title, $post_id);
update_field('status', 0, $post_id); // 注意:字段名需与 ACF 后台实际字段键名完全一致
}
}
? 重要提醒:
- update_field() 的第一个参数必须是 ACF 字段的 字段键(Field Key) 或 字段名称(Field Name),推荐使用字段名称(如 'points_latitude'),前提是该字段在 ACF 中已启用“Show in REST API”选项(ACF Pro v5.11+ 支持);
- 若使用免费版 ACF,务必确认字段已启用“REST API”支持(在字段编辑页勾选 Appears in REST API);
- 永远对用户输入执行 sanitize_text_field() 或更严格的过滤,防止 XSS 或注入风险;
- acf/save_post 钩子在所有 ACF 字段保存后触发,适合做最终校验或联动更新。
通过以上配置,即可实现前端一键创建含完整 ACF 数据的自定义文章,兼顾安全性、可维护性与兼容性。










