探究 WordPress `register_meta()` 函数的源码:如何使自定义元数据可被 Gutenberg 编辑和 REST API 访问。

各位观众老爷们,大家好!今天咱们来聊聊 WordPress 里一个非常重要的函数 register_meta(),看看它怎么让你的自定义字段在古腾堡编辑器(Gutenberg)里溜达,还能被 REST API 抓取。这玩意儿,说白了,就是让你辛辛苦苦定义的元数据,不光能存起来,还能方便地用起来。准备好了吗?咱们发车啦!

开场白:元数据,你家的“私房钱”

想象一下,你是个作家,写了一篇小说。除了文章内容,你可能还想记录一些额外的信息,比如:

  • 小说状态: 草稿、已发布、已废弃
  • 关键词: 科幻、爱情、冒险
  • 预计字数: 10万字

这些额外的信息,就是元数据。WordPress 默认的文章、页面都有一些元数据(比如作者、发布时间),但有时候我们需要更多。这时,register_meta() 就派上用场了。它能让你定义自己的“私房钱”,而且还能让 WordPress 知道这些“私房钱”的存在,方便你管理和使用。

register_meta(): 注册你的“私房钱”

register_meta() 函数的作用,简单来说,就是告诉 WordPress:“嘿,伙计,我这里有一些新的元数据,你得记住它们,并且允许我操作它们。”

它的基本语法是这样的:

register_meta( string $object_type, string $meta_key, array|string $args );
  • $object_type: 元数据所属的对象类型。比如 'post'(文章)、'page'(页面)、'user'(用户)等等。
  • $meta_key: 元数据的键名。也就是你给这个“私房钱”起的名字,比如 'novel_status''keywords'
  • $args: 一个数组,包含元数据的各种属性,比如类型、描述、是否允许公开访问等等。这是最重要的部分,稍后详细讲解。

$args 参数: “私房钱”的说明书

$args 参数决定了你的元数据的行为。它是一个数组,可以包含以下几个关键的键值对:

键名 类型 描述 默认值
type string 元数据的类型。可以是 'string'(字符串)、'integer'(整数)、'boolean'(布尔值)、'number'(浮点数)、'array'(数组)、'object'(对象)。 'string'
description string 元数据的描述,方便开发者理解。 ''
single bool 是否为单值元数据。如果为 true,则每个对象只能有一个该元数据的值;如果为 false,则可以有多个值(类似于文章的标签)。 false
sanitize_callback callable 一个回调函数,用于清理和验证元数据的值。在保存元数据之前,会调用这个函数。 null
auth_callback callable 一个回调函数,用于验证用户是否有权限修改元数据。如果用户没有权限,则无法修改元数据。 null
show_in_rest bool 是否在 REST API 中显示元数据。如果为 true,则可以通过 REST API 获取和修改元数据。这对于让古腾堡编辑器访问元数据至关重要。 false
default mixed 元数据的默认值。 ''
object_subtype string (仅适用于分类法,taxonomy) 对象子类型。例如,'category''post_tag' 或自定义分类法的名称。 ''
validate_callback callable (5.6+ 版本) 一个回调函数,用于在元数据保存到数据库之前验证它。如果验证失败,则元数据不会被保存。此函数应返回 true 以指示有效数据或 false 以指示无效数据。 null

代码实战:让小说状态在古腾堡里“抛头露面”

现在,我们来写一段代码,让小说状态(novel_status)这个元数据,能够在古腾堡编辑器里显示,并且可以通过 REST API 进行访问。

function register_novel_status_meta() {
    register_meta( 'post', 'novel_status', array(
        'type'              => 'string',
        'description'       => '小说状态(草稿、已发布、已废弃)',
        'single'            => true,
        'sanitize_callback' => 'sanitize_text_field', // 清理用户输入
        'auth_callback'     => function() {
            return current_user_can( 'edit_posts' ); // 只有能编辑文章的用户才能修改
        },
        'show_in_rest'      => true, // 重点!让 REST API 知道它的存在
        'default'           => 'draft', // 默认状态为草稿
    ) );
}
add_action( 'init', 'register_novel_status_meta' );

这段代码做了以下几件事:

  1. 定义了一个名为 register_novel_status_meta 的函数。
  2. 使用 register_meta() 函数注册了一个元数据,对象类型为 'post',键名为 'novel_status'
  3. 指定了元数据的类型为 'string',描述为 '小说状态(草稿、已发布、已废弃)'
  4. 设置了 singletrue,表示每篇文章只能有一个小说状态。
  5. 使用了 sanitize_text_field 函数清理用户输入,防止 XSS 攻击。
  6. 使用了一个匿名函数作为 auth_callback,只有具有 'edit_posts' 权限的用户才能修改这个元数据。
  7. 最关键的一步:设置 show_in_resttrue,让 REST API 能够访问这个元数据。
  8. 设置了默认值为 'draft'
  9. 使用 add_action( 'init', 'register_novel_status_meta' ) 将这个函数挂载到 init 钩子上,确保在 WordPress 初始化时执行。

古腾堡编辑器:让“私房钱”可视化

仅仅让 REST API 知道元数据的存在还不够,我们还需要让它在古腾堡编辑器里显示出来,方便用户编辑。这需要用到古腾堡的 JavaScript API。

首先,你需要创建一个 JavaScript 文件(比如 novel-status.js),然后将它注册到 WordPress 里。

function enqueue_novel_status_script() {
    wp_enqueue_script(
        'novel-status-script',
        plugin_dir_url( __FILE__ ) . 'novel-status.js',
        array( 'wp-blocks', 'wp-element', 'wp-components', 'wp-editor' ),
        filemtime( plugin_dir_path( __FILE__ ) . 'novel-status.js' )
    );
}
add_action( 'enqueue_block_editor_assets', 'enqueue_novel_status_script' );

这段代码会将 novel-status.js 文件加载到古腾堡编辑器中。

接下来,在 novel-status.js 文件中,你可以使用 wp.blocks.registerBlockSidebar() 函数来创建一个侧边栏面板,并在其中显示小说状态的选项。

wp.blocks.registerBlockSidebar(
    'novel-status/novel-status-panel',
    {
        title: '小说状态',
        icon: 'book',
        render: function() {
            var el = wp.element.createElement;
            var withSelect = wp.data.withSelect;
            var withDispatch = wp.data.withDispatch;
            var compose = wp.compose.compose;
            var SelectControl = wp.components.SelectControl;

            var NovelStatusSelectControl = compose(
                withSelect( function( select ) {
                    return {
                        meta: select( 'core/editor' ).getEditedPostAttribute( 'meta' ),
                    };
                } ),
                withDispatch( function( dispatch ) {
                    return {
                        setMeta: function( newMeta ) {
                            dispatch( 'core/editor' ).editPost( { meta: newMeta } );
                        },
                    };
                } )
            )( function( props ) {
                return el(
                    SelectControl,
                    {
                        label: '小说状态',
                        value: props.meta.novel_status || 'draft',
                        options: [
                            { label: '草稿', value: 'draft' },
                            { label: '已发布', value: 'published' },
                            { label: '已废弃', value: 'abandoned' },
                        ],
                        onChange: function( value ) {
                            props.setMeta( { ...props.meta, novel_status: value } );
                        },
                    }
                );
            } );

            return el(
                'div',
                { className: 'novel-status-panel' },
                el( NovelStatusSelectControl )
            );
        }
    }
);

这段 JavaScript 代码做了以下几件事:

  1. 使用 wp.blocks.registerBlockSidebar() 函数注册了一个侧边栏面板,标题为“小说状态”,图标为“book”。
  2. render 函数中,使用 wp.element.createElement 创建了一个 SelectControl 组件,用于显示小说状态的选项。
  3. 使用 wp.data.withSelect 函数获取文章的元数据。
  4. 使用 wp.data.withDispatch 函数更新文章的元数据。
  5. SelectControl 组件添加到侧边栏面板中。

REST API:让“私房钱”飞起来

现在,你的小说状态已经可以在古腾堡编辑器里编辑了。但是,如果你想通过 REST API 获取或修改小说状态,该怎么办呢?

由于我们在 register_meta() 中设置了 show_in_resttrue,所以 WordPress 会自动将 novel_status 元数据添加到 REST API 的响应中。

你可以使用以下 REST API 端点获取文章的元数据:

/wp-json/wp/v2/posts/<post_id>

其中 <post_id> 是文章的 ID。

在响应中,你会看到一个 meta 字段,其中包含了 novel_status 元数据的值。

要修改文章的元数据,你可以使用以下 REST API 端点:

/wp-json/wp/v2/posts/<post_id>

使用 PUTPOST 方法,并在请求体中包含 meta 字段,其中包含了要修改的元数据的值。

例如:

{
    "meta": {
        "novel_status": "published"
    }
}

高级用法:sanitize_callbackauth_callback

sanitize_callbackauth_callbackregister_meta() 函数中两个非常重要的参数,它们分别用于清理和验证元数据的值,以及验证用户是否有权限修改元数据。

  • sanitize_callback:保卫你的数据

sanitize_callback 参数接受一个回调函数,该函数接收元数据的值作为参数,并返回清理后的值。这个函数的作用是防止恶意用户输入恶意代码,比如 XSS 攻击。

WordPress 提供了一些内置的清理函数,比如 sanitize_text_fieldsanitize_emailsanitize_url 等。你可以根据元数据的类型选择合适的清理函数。

如果你需要更复杂的清理逻辑,可以自定义一个清理函数。

例如:

function sanitize_novel_status( $value ) {
    $allowed_statuses = array( 'draft', 'published', 'abandoned' );
    if ( in_array( $value, $allowed_statuses ) ) {
        return $value;
    } else {
        return 'draft'; // 如果值不在允许的范围内,则返回默认值
    }
}
  • auth_callback:守护你的权限

auth_callback 参数接受一个回调函数,该函数用于验证用户是否有权限修改元数据。如果用户没有权限,则无法修改元数据。

这个函数应该返回 true 如果用户有权限,否则返回 false

你可以使用 WordPress 的权限系统来验证用户权限。

例如:

function authorize_novel_status_update( $allowed, $meta_key, $object_id, $user_id, $cap, $caps ) {
    if ( 'novel_status' === $meta_key && ! current_user_can( 'edit_post', $object_id ) ) {
        return false; // 只有能编辑文章的用户才能修改
    }
    return $allowed;
}
add_filter( 'auth_post_meta_novel_status', 'authorize_novel_status_update', 10, 6 );

小结:让“私房钱”发挥最大价值

register_meta() 函数是 WordPress 中一个非常强大的工具,它可以让你定义自己的元数据,并且让这些元数据能够在古腾堡编辑器里显示,并且可以通过 REST API 进行访问。

通过合理地使用 register_meta() 函数,你可以让你的 WordPress 网站更加灵活和强大。

记住,show_in_rest 是让你的元数据在古腾堡和 REST API 中“抛头露面”的关键。而 sanitize_callbackauth_callback 则是保护你的数据和权限的卫士。

希望今天的讲座对你有所帮助。下次再见!

发表回复

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