EP073. “给已有 REST 字段加自定义属性(register_rest_field)”
🔒 登录后可标记已读之前 Section 13-14 是从 JS 那头「消费」wp/v2/posts 这类内建 REST API,这一讲开始换个角度:从 PHP 这头「定制」REST API 输出的原始 JSON。需求场景是 search overlay 里希望博客文章结果显示成「标题 by 作者名」,但 wp/v2/posts 默认只给作者的 ID(author 字段),没有人类可读的名字。这一讲用 register_rest_field() 往 post 类型的 REST 输出里加一个新字段 authorName,值来自 get_the_author(),然后在 Search.js 里用这个新字段拼出「by 作者名」文字。
涉及文件
wp-content/themes/fictional-university-theme/functions.php(修改,加在文件最开头)wp-content/themes/fictional-university-theme/src/modules/Search.js(修改,getResults()方法里的模板字符串)
代码实现
functions.php 最开头新增(放在 <?php 后第一行):
<?php
// 新增:给 wp/v2/posts 的 REST 输出加一个 authorName 字段
function university_custom_rest() {
register_rest_field('post', 'authorName', array(
'get_callback' => function() {return get_the_author();}
));
}
add_action('rest_api_init', 'university_custom_rest');
Search.js 里 getResults() 方法内,拼 HTML 的那一行改成用三元运算符判断,只有博客文章(type == "post")才显示「by 作者名」:
// src/modules/Search.js(getResults() 方法内,模板字符串片段)
${combinedResults.map(item => `<li><a href="${item.link}">${item.title.rendered}</a> ${item.type == "post" ? `by ${item.authorName}` : ""}</li>`).join("")}
要点:
register_rest_field($post_type, $field_name, $args)三个参数:第一个是要定制的 post type(post、page,也可以是自定义 post type),第二个是新字段名(自己取,这里叫authorName),第三个是数组,本讲只用了get_callback。get_callback是一个匿名函数,函数返回什么,这个新字段的值就是什么——可以是任何 PHP 能算出来的东西(ACF 字段值、裁切过的图片 URL、甚至一个自定义查询的结果都行),返回值最终会被转成 JSON。- 这个改动要挂在
rest_api_init这个 hook 上,不是init。 - 因为
page这个 post type 没有注册authorName字段,所以 JS 那边如果不加判断,搜索结果里的页面会显示成「by undefined」。这就是为什么Search.js里用item.type == "post" ? ... : ""的三元表达式做条件判断——模板字符串里不能直接写 if,只能用三元运算符代替。
[截图:浏览器直接访问 wp-json/wp/v2/posts,查看 JSON 响应里新增的 authorName 字段]
Hook / Function 速查
| 名称 | 类型 | 用途 |
|---|---|---|
register_rest_field($post_type, $field_name, $args) | WP 内建 function | 给指定 post type 的 REST API 输出追加一个自定义字段 |
rest_api_init | WP hook | REST API 初始化时触发,定制 REST 输出要挂在这个 hook 上(不是 init) |
get_the_author() | WP 内建 function(返回值) | 返回当前文章作者的人类可读昵称 |
常见坑
- 只给
post类型注册了authorName字段,page类型没有这个字段,如果 JS 不做类型判断直接拼by ${item.authorName},页面类型的搜索结果会显示「by undefined」。
延伸 / 后续讲座会用到
下一讲(EP074)不再是修改已有的 REST 输出,而是从零建一个完全自定义的 REST 路由(university/v1/search),用来实现真正的跨内容类型搜索——因为 WordPress 内建搜索逻辑不认识自定义字段和 post 之间的关系(比如 program 和 professor 的关联),搜不到这些内容。
Sources
Udemy:
- Become a WordPress Developer: Unlocking Power With Code — Section 15, EP073