解析 WordPress `register_rest_field()` 函数源码:如何为 REST API 响应添加自定义字段。

各位观众老爷们,大家好!我是今天的主讲人,一个在代码堆里摸爬滚打多年的老码农。今天咱们来聊聊 WordPress REST API 的一个超级实用的小技巧:register_rest_field() 函数,以及如何用它来给你的 API 响应添加自定义字段,让你的数据更加丰满,姿势更加优雅!

开场白:为什么我们需要自定义字段?

话说回来,WordPress 默认的 REST API 提供的字段有时候并不能完全满足我们的需求。比如,你可能想要在文章的 API 响应中添加作者的头像,或者某个自定义字段的值,或者一些经过计算的统计数据。这时候,register_rest_field() 就派上大用场了!它就像一个万能的补丁,允许你轻松地往 API 响应中塞入任何你想要的数据。

register_rest_field() 函数:闪亮登场!

register_rest_field() 函数是 WordPress 提供的用于注册自定义 REST API 字段的函数。它的基本语法如下:

register_rest_field(
    string   $object_type,
    string   $attribute,
    array    $args
);
  • $object_type (string, required): 你要往哪个对象类型添加字段?比如 'post' (文章), 'page' (页面), 'user' (用户), 'taxonomy' (分类法) 等等。也可以是自定义文章类型,比如 'product'
  • $attribute (string, required): 你要添加的字段的名称。这个名字将会出现在 API 响应中,所以要起一个有意义的名字,比如 'author_avatar' 或者 'custom_field_value'
  • $args (array, required): 一个包含了各种参数的数组,用于配置字段的行为。最重要的参数是 get_callbackupdate_callback

    • get_callback (callable, required): 一个回调函数,用于获取字段的值。这个函数接收三个参数:$object (当前对象,比如文章对象), $field_name (字段名称), $request (请求对象)。它必须返回字段的值。
    • update_callback (callable, optional): 一个回调函数,用于更新字段的值。这个函数接收三个参数:$value (要设置的值), $object (当前对象), $field_name (字段名称)。这个参数是可选的,只有当你需要允许通过 API 更新字段时才需要设置。
    • schema (array, optional): 一个描述字段结构的数组,用于定义字段的数据类型、描述等信息。这有助于 API 客户端理解字段的含义。

实战演练:给文章添加作者头像字段

咱们来一个最常见的例子:给文章的 API 响应添加作者头像字段。

add_action( 'rest_api_init', 'register_author_avatar_field' );

function register_author_avatar_field() {
    register_rest_field(
        'post', // 对象类型:文章
        'author_avatar', // 字段名称:author_avatar
        array(
            'get_callback'    => 'get_author_avatar', // 获取字段值的回调函数
            'update_callback' => null, // 不允许更新,设为 null
            'schema'          => array(
                'description' => '作者头像 URL',
                'type'        => 'string',
                'format'      => 'url',
                'context'     => array( 'view', 'edit' ), // 在哪些上下文中显示
            ),
        )
    );
}

function get_author_avatar( $object, $field_name, $request ) {
    // 获取作者 ID
    $author_id = $object['author'];

    // 获取作者头像 URL
    $author_avatar_url = get_avatar_url( $author_id, array( 'size' => 96 ) );

    return $author_avatar_url;
}

这段代码做了什么呢?

  1. add_action( 'rest_api_init', 'register_author_avatar_field' );: 这个函数会在 REST API 初始化时执行 register_author_avatar_field 函数,确保我们的字段注册在 API 可用之前完成。
  2. register_rest_field( 'post', 'author_avatar', ... );: 注册一个名为 author_avatar 的字段,关联到 post 对象类型。
  3. 'get_callback' => 'get_author_avatar': 指定 get_author_avatar 函数作为获取字段值的回调函数。
  4. get_author_avatar( $object, $field_name, $request ): 这个函数接收文章对象 $object,从中提取作者 ID,然后使用 get_avatar_url() 函数获取作者头像的 URL。最后,返回头像 URL。
  5. 'schema' => ...: 定义了字段的 schema,告诉 API 客户端这个字段是一个字符串类型的 URL,描述是“作者头像 URL”,并且在 viewedit 上下文中显示。

现在,当你通过 REST API 请求文章数据时,你会发现响应中多了一个 author_avatar 字段,里面包含了作者头像的 URL!

更上一层楼:获取自定义字段的值

假设你有一个自定义字段,名为 _my_custom_field,你想把它添加到 API 响应中。

add_action( 'rest_api_init', 'register_custom_field' );

function register_custom_field() {
    register_rest_field(
        'post',
        'custom_field_value',
        array(
            'get_callback'    => 'get_custom_field_value',
            'update_callback' => 'update_custom_field_value', // 允许更新
            'schema'          => array(
                'description' => '自定义字段的值',
                'type'        => 'string',
                'context'     => array( 'view', 'edit' ),
            ),
        )
    );
}

function get_custom_field_value( $object, $field_name, $request ) {
    // 获取自定义字段的值
    $custom_field_value = get_post_meta( $object['id'], '_my_custom_field', true );

    return $custom_field_value;
}

function update_custom_field_value( $value, $object, $field_name ) {
    if ( ! current_user_can( 'edit_post', $object->ID ) ) {
        return new WP_Error( 'rest_cannot_edit',
            __( '您没有权限编辑该文章。', 'your-textdomain' ),
            array( 'status' => rest_authorization_required_code() )
        );
    }

    if ( ! is_string( $value ) ) {
        return new WP_Error( 'rest_invalid_type',
            __( '自定义字段的值必须是字符串。', 'your-textdomain' ),
            array( 'status' => 400 )
        );
    }

    // 更新自定义字段的值
    update_post_meta( $object->ID, '_my_custom_field', sanitize_text_field( $value ) );

    return true; // 返回 true 表示更新成功
}

这个例子中,get_custom_field_value 函数使用 get_post_meta() 函数获取自定义字段的值,并返回它。update_custom_field_value 函数使用 update_post_meta更新自定义字段的值。同时,这里加入了权限验证和数据类型验证,保证更新的安全性和数据的有效性。

深入挖掘:$request 对象

get_callback 函数接收的第三个参数 $request 是一个 WP_REST_Request 对象,它包含了当前 API 请求的所有信息,比如请求方法(GET, POST, PUT, DELETE)、请求参数、请求头等等。你可以使用 $request 对象来根据不同的请求参数返回不同的值。

例如,你可以根据请求参数来决定返回作者头像的大小:

function get_author_avatar( $object, $field_name, $request ) {
    // 获取请求参数
    $size = $request->get_param( 'size' );

    // 如果请求中指定了 size 参数,则使用指定的尺寸,否则使用默认尺寸 96
    $size = ! empty( $size ) ? intval( $size ) : 96;

    // 获取作者 ID
    $author_id = $object['author'];

    // 获取作者头像 URL
    $author_avatar_url = get_avatar_url( $author_id, array( 'size' => $size ) );

    return $author_avatar_url;
}

现在,你可以通过 ?size=200 这样的 URL 参数来指定作者头像的大小了!例如:your-site.com/wp-json/wp/v2/posts/1?size=200

高级技巧:使用 update_callback 更新字段

如果你想允许通过 REST API 更新你的自定义字段,你需要提供一个 update_callback 函数。这个函数接收三个参数:$value (要设置的值), $object (当前对象), $field_name (字段名称)。

update_callback 函数中,你需要进行以下操作:

  1. 权限验证: 确保当前用户有权限更新该对象。
  2. 数据验证: 确保 $value 的值是有效的。
  3. 更新数据: 使用 WordPress 提供的函数(比如 update_post_meta())更新数据。
  4. 返回结果: 返回 true 表示更新成功,返回 WP_Error 对象表示更新失败。

注意事项:安全第一!

在使用 register_rest_field() 函数时,一定要注意安全问题。

  • 权限验证:get_callbackupdate_callback 函数中,一定要进行权限验证,确保只有授权用户才能访问和修改数据。
  • 数据验证:update_callback 函数中,一定要对 $value 进行数据验证,防止恶意用户注入恶意代码。
  • 数据清理:update_callback 函数中,一定要对 $value 进行数据清理,防止 XSS 攻击。

代码示例:用户自定义字段的 REST API

add_action( 'rest_api_init', 'register_user_custom_field' );

function register_user_custom_field() {
    register_rest_field(
        'user', // 对象类型:用户
        'custom_user_field', // 字段名称
        array(
            'get_callback'    => 'get_user_custom_field',
            'update_callback' => 'update_user_custom_field',
            'schema'          => array(
                'description' => '用户的自定义字段',
                'type'        => 'string',
                'context'     => array( 'view', 'edit' ),
            ),
        )
    );
}

function get_user_custom_field( $user, $field_name, $request ) {
    return get_user_meta( $user['id'], 'my_custom_user_field', true );
}

function update_user_custom_field( $value, $user, $field_name ) {
    if ( ! current_user_can( 'edit_user', $user->ID ) ) {
        return new WP_Error( 'rest_cannot_edit', '没有权限编辑该用户。', array( 'status' => rest_authorization_required_code() ) );
    }

    if ( ! is_string( $value ) ) {
        return new WP_Error( 'rest_invalid_type', '自定义字段的值必须是字符串。', array( 'status' => 400 ) );
    }

    update_user_meta( $user->ID, 'my_custom_user_field', sanitize_text_field( $value ) );
    return true;
}

这个例子展示了如何给用户对象添加自定义字段,并允许通过 API 更新。

表格总结:register_rest_field() 参数详解

参数 类型 是否必须 描述
$object_type string 你要往哪个对象类型添加字段?比如 'post' (文章), 'page' (页面), 'user' (用户) 等等。
$attribute string 你要添加的字段的名称。这个名字将会出现在 API 响应中。
$args array 一个包含了各种参数的数组,用于配置字段的行为。
get_callback callable 一个回调函数,用于获取字段的值。它接收三个参数:$object (当前对象), $field_name (字段名称), $request (请求对象)。
update_callback callable 一个回调函数,用于更新字段的值。它接收三个参数:$value (要设置的值), $object (当前对象), $field_name (字段名称)。
schema array 一个描述字段结构的数组,用于定义字段的数据类型、描述等信息。

常见问题答疑

  • Q: 我添加的字段没有显示在 API 响应中,怎么办?

    • A: 首先,确保你的代码已经正确执行,并且没有报错。其次,检查你的 schema 中的 context 参数,确保你的字段在当前上下文中是可见的。最后,清除 WordPress 的缓存,有时候缓存会导致 API 响应没有更新。
  • Q: 我如何知道 $object 对象中包含哪些数据?

    • A: 你可以使用 var_dump( $object ) 或者 error_log( print_r( $object, true ) ) 来打印 $object 对象的内容,看看里面包含了哪些字段。
  • Q: 我可以使用 register_rest_field() 函数来修改 WordPress 核心字段吗?

    • A: 不建议这样做。虽然你可以使用 register_rest_field() 函数来覆盖 WordPress 核心字段,但这可能会导致一些意想不到的问题。最好还是添加自定义字段,而不是修改核心字段。

总结:灵活运用,打造个性化 API

register_rest_field() 函数是 WordPress REST API 中一个非常强大的工具,它可以让你轻松地给 API 响应添加自定义字段,打造个性化的 API。只要你掌握了它的基本用法,并且注意安全问题,你就可以用它来做很多有趣的事情。

好了,今天的讲座就到这里。希望大家能够灵活运用 register_rest_field() 函数,让你的 WordPress REST API 更加强大! 散会!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注