分析 WordPress `register_meta()` 函数的源码:如何将元数据暴露给 REST API,并定义其类型和权限。

咳咳,各位观众老爷们,女士们先生们,欢迎来到今天的“WordPress元数据大冒险”讲座!我是你们的导游,江湖人称“代码老司机”,今天带大家深入挖掘 register_meta() 这个看似不起眼,实则暗藏玄机的函数,看看它是如何把元数据(也就是我们常说的自定义字段)华丽丽地展现在 REST API 的舞台上,以及如何赋予它们类型和权限,让它们在江湖上行走得安全又体面。

准备好了吗?让我们发车!

第一站:register_meta() 函数的“前世今生”

在WordPress的世界里,register_meta() 函数就像一个魔法师,它能将自定义字段变成REST API眼中可以识别和操作的对象。简单来说,它的作用就是:

  1. 注册元数据: 告诉WordPress,某个自定义字段是“合法的”,应该被纳入管理。
  2. 定义元数据属性: 比如它的类型、权限、是否能在REST API中显示等等。
  3. 暴露给REST API: 如果你愿意,它可以让这个自定义字段通过REST API被读取、修改和删除。

它的基本语法如下:

register_meta(
    string   $meta_type,
    string   $meta_key,
    array    $args = array()
);
  • $meta_type: 元数据所属的对象类型,比如 postuserterm等等。
  • $meta_key: 元数据的键名,也就是自定义字段的名字,比如 _my_custom_field。注意,通常我们会在自定义字段前面加个下划线_,表示它是内部使用的,但通过 register_meta() 注册后,即使带下划线,也可以在REST API中暴露出来。
  • $args: 一个数组,用于定义元数据的各种属性,这是我们今天的主角,稍后会详细讲解。

第二站:$args 数组的“七十二变”

$args 数组是 register_meta() 函数的核心,它决定了元数据的行为。我们来看看它有哪些重要的参数:

参数名 类型 描述
type string 元数据的类型,可以是 string (默认), integer, number, boolean, object, array。 这个类型信息会被 REST API 使用,用于验证数据的格式。
description string 元数据的描述,会在 REST API 的 schema 中显示,方便开发者了解这个字段的作用。
single boolean 是否为单值元数据。 true 表示一个对象只有一个值 (默认), false 表示一个对象可以有多个值。
sanitize_callback callable 用于清理和验证元数据的回调函数。 在保存元数据之前,这个函数会被调用,确保数据安全有效。
auth_callback callable 用于验证用户是否有权限读取或修改元数据的回调函数。 这个函数会返回 truefalse,决定是否允许访问。
show_in_rest boolean 是否在 REST API 中显示元数据。 true 表示显示, false 表示不显示 (默认)。 也可以是一个数组,用于更精细地控制 REST API 的显示方式。
default mixed 元数据的默认值。 如果元数据不存在,REST API 会返回这个默认值。
schema array 自定义 REST API schema。 可以更详细地定义元数据的类型、格式、描述等信息。 如果设置了 show_in_resttrue,但没有提供 schema,WordPress 会尝试根据 typesingle 自动生成 schema。 但自定义 schema 可以提供更精确的控制。

接下来,我们重点关注 show_in_resttypeauth_callback 这几个参数,看看它们是如何控制元数据在 REST API 中的行为的。

第三站:show_in_rest:元数据在 REST API 中的“曝光率”

show_in_rest 参数决定了元数据是否会在 REST API 中显示。它可以是:

  • false (默认): 不显示。
  • true: 显示在 REST API 的响应中。
  • 一个数组: 更精细地控制显示方式。

如果设置为 true,元数据会以默认的方式显示在 REST API 的响应中。例如,对于文章(post)类型的元数据,它会出现在 wp/v2/posts/{id} 接口的响应中。

// 让 _my_custom_field 在 REST API 中显示
register_meta( 'post', '_my_custom_field', array(
    'type'         => 'string',
    'show_in_rest' => true,
    'single'       => true,
) );

如果想要更精细地控制显示方式,可以使用数组:

register_meta( 'post', '_my_custom_field', array(
    'type'         => 'string',
    'show_in_rest' => array(
        'name'   => 'my_custom_field', // 在 REST API 中显示的字段名,可以自定义
        'schema' => array(
            'type'        => 'string',
            'description' => '我的自定义字段',
            'readonly'    => true, // 只读,不允许通过 REST API 修改
        ),
    ),
    'single'       => true,
) );

在这个例子中,我们:

  • 将元数据在 REST API 中显示的字段名改为了 my_custom_field,而不是默认的 _my_custom_field
  • 自定义了 schema,添加了描述信息,并且设置了 readonlytrue,表示这个字段只能读取,不能通过 REST API 修改。

第四站:type:元数据的“身份证”

type 参数定义了元数据的类型,可以是 stringintegernumberbooleanobjectarray。 这个类型信息会被 REST API 使用,用于验证数据的格式。

// 定义 _my_age 为整数类型
register_meta( 'user', '_my_age', array(
    'type'         => 'integer',
    'show_in_rest' => true,
    'single'       => true,
) );

// 定义 _my_settings 为对象类型
register_meta( 'post', '_my_settings', array(
    'type'         => 'object',
    'show_in_rest' => true,
    'single'       => true,
) );

如果设置了类型,REST API 在接收到数据时,会进行类型验证。如果类型不匹配,会返回错误。这可以有效地防止无效数据被保存到数据库中。

第五站:auth_callback:元数据的“守门神”

auth_callback 参数是一个回调函数,用于验证用户是否有权限读取或修改元数据。 这个函数会接收三个参数:

  • $allowed: 一个布尔值,表示是否允许访问 (默认为 false)。
  • $meta_key: 元数据的键名。
  • $object_id: 对象 ID (比如文章 ID、用户 ID 等)。
  • $user_id: 用户 ID。
  • $capability: 需要的权限。
  • $args: register_meta 函数的参数。

你需要在这个函数中编写逻辑,判断用户是否有权限访问元数据,并返回 truefalse

// 验证用户是否有权限修改 _my_secret_data
function my_auth_callback( $allowed, $meta_key, $object_id, $user_id, $capability, $args ) {
    // 只有管理员才能修改
    if ( current_user_can( 'administrator' ) ) {
        return true;
    }

    return false;
}

register_meta( 'post', '_my_secret_data', array(
    'type'          => 'string',
    'show_in_rest'  => true,
    'single'        => true,
    'auth_callback' => 'my_auth_callback',
) );

在这个例子中,只有管理员才能修改 _my_secret_data 字段。其他用户尝试修改时,REST API 会返回 403 Forbidden 错误。

第六站:实战演练:一个完整的例子

让我们结合以上知识,创建一个完整的例子。假设我们要为一个文章添加一个自定义字段 _article_views,用于记录文章的浏览量。我们希望:

  • 浏览量是整数类型。
  • 在 REST API 中显示,字段名为 article_views
  • 只有管理员才能修改浏览量。
  • 默认值为 0。

代码如下:

<?php
/**
 * Plugin Name: Register Meta Example
 * Description: Demonstrates how to use register_meta() to expose metadata to the REST API.
 */

add_action( 'rest_api_init', 'register_article_views_meta' );

function register_article_views_meta() {
    register_meta( 'post', '_article_views', array(
        'type'          => 'integer',
        'description'   => '文章浏览量',
        'single'        => true,
        'show_in_rest'  => array(
            'name' => 'article_views',
            'schema' => array(
                'type' => 'integer',
                'description' => '文章浏览量',
                'context' => array( 'view', 'edit' ), // 允许在 "view" 和 "edit" 上下文中显示
            ),
        ),
        'auth_callback' => 'check_article_views_permission',
        'default'       => 0,
        'sanitize_callback' => 'sanitize_article_views',
    ) );
}

/**
 * 验证用户是否有权限修改文章浏览量.
 *
 * @param bool   $allowed  Whether the user is allowed to edit the meta field.
 * @param string $meta_key The meta key.
 * @param int    $object_id The ID of the object the meta is attached to.
 * @param int    $user_id The ID of the user attempting to perform the action.
 * @param string $capability The capability type.
 * @param array  $args Array of extra parameters.
 *
 * @return bool
 */
function check_article_views_permission( $allowed, $meta_key, $object_id, $user_id, $capability, $args ) {
    // 只有管理员才能修改
    if ( current_user_can( 'administrator' ) ) {
        return true;
    }

    return false;
}

/**
 * 清理文章浏览量.
 *
 * @param mixed $value The raw meta value.
 *
 * @return int The sanitized value.
 */
function sanitize_article_views( $value ) {
    return intval( $value ); // 确保是整数
}

在这个例子中,我们:

  1. 使用 register_meta() 注册了 _article_views 元数据。
  2. 定义了它的类型为 integer
  3. 设置了 show_in_rest 为数组,将字段名改为了 article_views,并自定义了 schema。
  4. 使用 auth_callback 验证用户权限,只有管理员才能修改。
  5. 设置了默认值为 0。
  6. 使用 sanitize_callback 清理数据,确保是整数类型。

现在,你可以通过 REST API 获取文章信息,看到 article_views 字段,并且只有管理员才能修改它。

第七站:注意事项和“坑”

在使用 register_meta() 函数时,有一些需要注意的地方:

  • 避免重复注册: 不要多次注册同一个元数据,否则可能会导致冲突。
  • 选择合适的类型: 根据元数据的实际类型选择合适的 type 参数,这可以提高数据的准确性和安全性。
  • 编写完善的 auth_callback auth_callback 是保护元数据的关键,务必编写完善的逻辑,确保只有授权用户才能访问。
  • 使用 sanitize_callback 清理数据: sanitize_callback 可以防止恶意数据被保存到数据库中,提高系统的安全性。
  • 了解 REST API 的工作原理: 熟悉 REST API 的基本概念,才能更好地使用 register_meta() 函数。

第八站:总结与展望

register_meta() 函数是 WordPress 中一个非常强大的工具,它可以让你轻松地将自定义字段暴露给 REST API,并且可以灵活地控制它们的类型和权限。 掌握了 register_meta() 函数,你就可以构建更加强大和灵活的 WordPress 应用。

今天的“WordPress元数据大冒险”就到这里了。希望大家能够通过今天的学习,更加深入地了解 register_meta() 函数,并且能够在实际项目中灵活运用。

感谢大家的观看,我们下期再见! (挥手)

发表回复

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