修改回复

WordPress REST API 的默认端点旨在默认返回为大多数站点和用例提供的数据,但通常情况下,您需要在各种对象类型的响应中访问或公开其他数据。

与 WordPress 的其余部分一样,REST API 被设计为具有高度可扩展性以满足这些需求。register_rest_field 本指南详细介绍了如何使用和函数将附加数据添加到默认端点的响应register_meta 。您可以使用这些函数将字段添加到 REST API 支持的任何对象类型。这些自定义字段可以支持获取和更新操作。

关于更改响应的重要说明

警报:
从核心 REST API 端点响应更改或删除数据可能会破坏插件或 WordPress 核心行为,应尽可能避免。

API 在 API 响应中公开了许多字段,包括您可能不需要的内容,或者可能不适合您的站点工作方式的内容。虽然修改或删除 REST API 响应中的字段很诱人,但这导致期望标准响应的 API 客户端出现问题。这包括移动客户端、帮助您管理站点的第三方工具或 wp-admin 本身。

您可能只需要少量数据,但请务必记住,API 是向所有客户端公开接口,而不仅仅是您正在处理的功能。改变反应是危险的。

添加字段并不危险,因此如果您需要修改数据,最好复制字段而不是使用修改后的数据。从不鼓励删除字段;如果您需要取回较小的数据子集,请改用_fields参数或使用上下文。

如果您必须从现有上下文中删除字段,则应确保该行为是选择加入的,例如通过提供自定义查询参数来触发字段删除。

API 不能阻止您更改响应,但代码的结构强烈反对这样做。在内部,字段注册由过滤器提供支持,如果您绝对没有其他选择,可以使用这些。

使用register_rest_field对比register_meta

有两种方法可用于将数据添加到 WordPress REST API 响应,register_rest_field以及register_meta.

register_rest_field可用于向任何 REST API 响应添加任意字段,并且可用于使用 API 读取和写入数据。要注册一个新的 REST 字段,您必须提供自己的回调函数来获取或设置该字段的值,并手动为该字段指定您自己的架构定义。

register_meta用于将现有自定义元值列入白名单,以便通过 REST API 进行访问。通过将元字段的show_in_rest参数设置为true,该字段的值将暴露.meta在端点响应中的键上,并且 WordPress 将处理设置回调以读取和写入该元键。这比 简单得多register_rest_field,但有一个警告:

警报:
show_in_rest在 WordPress 4.9.8 之前,设置为using 的 元字段register_meta是为给定类型的所有对象注册的。如果一种自定义帖子类型显示元字段,则所有自定义帖子类型都将显示该元字段。从 WordPress 4.9.8 开始,可以使用允许将元键的使用减少到特定帖子类型的参数register_metaobject_subtype

在 WordPress 5.3 之前,register_meta只能支持标量值(stringintegernumberboolean。WordPress 5.3 添加了对objectarray类型的支持。

向 API 响应添加自定义字段

使用register_rest_field

register_rest_field 函数是向 REST API 响应对象添加字段的最灵活的方式。它接受三个参数:

  1. $object_type:对象的名称,作为一个字符串,或者一个对象名称的数组,该字段正在为其注册。这可能是核心类型,如“post”、“terms”、“meta”、“user”或“comment”,但也可以是自定义帖子类型的字符串名称。
  2. $attribute: 字段名称。此名称将用于定义响应对象中的键。
  3. $args: 一个包含键的数组,这些键定义用于检索字段值 ('get_callback')、更新字段值 ('update_callback') 以及定义其模式 ('schema') 的回调函数。

$args 数组的每个键都是可选的,但如果不使用,则不会添加该功能。这意味着您可以指定一个回调函数来读取值,并在需要时省略更新回调以使该字段成为只读。

应在操作中注册字段rest_api_init。使用此操作而不是init将阻止在不使用 REST API 的 WordPress 请求期间发生字段注册。

例子

在评论回复中读写一个额外的字段

<?php
add_action( 'rest_api_init', function () {
    register_rest_field( 'comment', 'karma', array(
        'get_callback' => function( $comment_arr ) {
            $comment_obj = get_comment( $comment_arr['id'] );
            return (int) $comment_obj->comment_karma;
        },
        'update_callback' => function( $karma, $comment_obj ) {
            $ret = wp_update_comment( array(
                'comment_ID'    => $comment_obj->comment_ID,
                'comment_karma' => $karma
            ) );
            if ( false === $ret ) {
                return new WP_Error(
                  'rest_comment_karma_failed',
                  __( 'Failed to update comment karma.' ),
                  array( 'status' => 500 )
                );
            }
            return true;
        },
        'schema' => array(
            'description' => __( 'Comment karma.' ),
            'type'        => 'integer'
        ),
    ) );
} );

这个例子说明了添加一个字段调用karma 到帖子的响应。它起作用是因为该comment_karma 字段存在,但未被核心使用。请注意,comment karma 的实际实现需要使用单独的端点。

这是一个基本的例子;仔细考虑您的特定字段可能需要哪些权限检查或错误处理。

register_rest_field工作原理

REST API 基础结构在内部使用全局变量$wp_rest_additional_fields 来保存要添加到每个对象类型的响应字段。REST API 提供了register_rest_field一个实用函数来添加到这个全局变量中。应避免直接添加到全局变量以确保向前兼容。

对于每个对象类型——帖子或用户、术语、评论等——$wp_rest_additional_fields包含一个字段定义数组,其中包含用于检索或更新字段值的回调。

在 REST API 中使用已注册的元数据

register_meta函数简化了为特定对象类型定义元字段的过程。通过'show_in_rest' => true在注册新元密钥时进行设置,可以通过 REST API 访问该密钥。

在帖子回复中读取和写入帖子元字段

<?php
// The object type. For custom post types, this is 'post';
// for custom comment types, this is 'comment'. For user meta,
// this is 'user'.
$object_type = 'post';
$meta_args = array( // Validate and sanitize the meta value.
    // Note: currently (4.7) one of 'string', 'boolean', 'integer',
    // 'number' must be used as 'type'. The default is 'string'.
    'type'         => 'string',
    // Shown in the schema for the meta key.
    'description'  => 'A meta key associated with a string meta value.',
    // Return a single value of the type.
    'single'       => true,
    // Show in the WP REST API response. Default: false.
    'show_in_rest' => true,
);
register_meta( $object_type, 'my_meta_key', $meta_args );

此示例显示如何允许读取和写入后元字段。这将允许该字段通过 POST 请求更新wp-json/wp/v2/posts/<post-id>或通过 POST 请求连同帖子一起创建wp-json/wp/v2/posts/

请注意,对于在自定义帖子类型上注册的元字段,帖子类型必须具有custom-fields 支持。否则元字段将不会出现在 REST API 中。

帖子类型特定元

WordPress 4.9.8 添加了对通过使用register_post_metaregister_term_meta函数为特定帖子类型或分类法注册元数据的支持。它们遵循相同的规则,register_meta但接受帖子类型或分类法作为它们的第一个参数而不是对象类型。以下代码将注册my_meta_key上面的示例,但仅适用于page自定义帖子类型。

$meta_args = array(
    'type'         => 'string',
    'description'  => 'A meta key associated with a string meta value.',
    'single'       => true,
    'show_in_rest' => true,
);
register_post_meta( 'page', 'my_meta_key', $meta_args );

对象元类型

WordPress 5.3 添加了对在注册元时使用object 类型的支持。重要的object是指一个JSON对象,这个相当于PHP中的关联数组。

注册objectmeta 时,仅设置typetoobject是不够的,您还需要告知 WordPress 允许哪些属性。这是通过在注册元数据时编写 JSON Schema 来完成的。

例如,以下代码示例注册了一个名为“release”的发布元字段,它接受给定的 JSON 数据。

{
  "meta": {
    "release": {
      "version": "5.2",
      "artist": "Jaco"
    }
  }
}
register_post_meta(
    'post',
    'release',
    array(
        'single'       => true,
        'type'         => 'object',
        'show_in_rest' => array(
            'schema' => array(
                'type'       => 'object',
                'properties' => array(
                    'version' => array(
                        'type' => 'string',
                    ),
                    'artist'  => array(
                        'type' => 'string',
                    ),
                ),
            ),
        ),
    )
);

请注意,它show_in_rest变成了一个数组而不是true,并且为键指定了一个 Json 模式schema。然后每个属性都列在properties数组中。至少,每个属性都必须指定一个type,但rest_validate_value_from_schema也可以使用任何可以理解的 JSON Schema 关键字。

附加属性

默认情况下,属性列表是严格的白名单。如果在请求中发送了未列出的属性,REST API 将返回错误:your_property is not a valid property of Object.。如果您事先不知道属性名称,additionalProperties可以使用关键字。additionalProperties接受用于验证未知属性的 JSON 模式。例如,要强制任何其他属性都是数字,可以使用以下代码。

{
  "meta": {
    "release": {
      "version": "5.2",
      "artist": "Jaco",
      "unknown_field": 5.3
    }
  }
}
register_post_meta(
    'post',
    'version',
    array(
        'single'       => true,
        'type'         => 'object',
        'show_in_rest' => array(
            'schema' => array(
                'type'                 => 'object',
                'properties'           => array(
                    'version' => array(
                        'type' => 'string',
                    ),
                    'artist'  => array(
                        'type' => 'string',
                    ),
                ),
                'additionalProperties' => array(
                    'type' => 'number',
                ),
            ),
        ),
    )
);

additionalProperties可以设置为 true 以允许任何格式的未知属性,但不推荐这样做。

数组元类型

WordPress 5.3 还增加了对使用array type 的支持。重要的array是指一个JSON数组,这相当于PHP中的数值数组。

注册arraymeta 时,仅设置typetoarray是不够的,您需要告知 WordPress 数组中项目的预期格式。这是通过在注册元数据时编写 JSON Schema 条目来完成的。

如果您不提供此值,register_meta将返回 false 并发出以下警告:When registering an "array" meta type to show in the REST API, you must specify the schema for each array item in "show_in_rest.schema.items".

以下代码示例注册了一个名为“projects”的后元字段,其中包含项目名称列表。它接受给定的 JSON 数据。

{
  "meta": {
    "projects": [
      "WordPress",
      "BuddyPress"
    ]
  }
}
register_post_meta(
    'post',
    'projects',
    array(
        'single'       => true,
        'type'         => 'array',
        'show_in_rest' => array(
            'schema' => array(
                'type'  => 'array',
                'items' => array(
                    'type' => 'string',
                ),
            ),
        ),
    )
);

请注意,它再次show_in_rest变为数组而不是,true并且为键指定了 JSON 模式schema
关键字items用于定义 JSON 模式以验证每个数组成员。它可以是标量类型string,如object.

例如,要接受给定的 JSON 数据,将使用以下元注册。

{
  "meta": {
    "projects": [
      {
        "name": "WordPress",
        "website": "https://wordpress.org"
      },
      {
        "name": "BuddyPress",
        "website": "https://buddypress.org"
      }
    ]
  }
}
register_post_meta(
    'post',
    'projects',
    array(
        'single'       => true,
        'type'         => 'array',
        'show_in_rest' => array(
            'schema' => array(
                'items' => array(
                    'type'       => 'object',
                    'properties' => array(
                        'name'    => array(
                            'type' => 'string',
                        ),
                        'website' => array(
                            'type'   => 'string',
                            'format' => 'uri',
                        ),
                    ),
                ),
            ),
        ),
    )
);

警报:该array类型强制数组键是从 0 开始的连续整数。数组将使用重新索引array_values

非单一元数据

非单个元字段每个对象都有一组值,而不是每个对象一个值。这些值中的每一个都存储在元表中的单独行中。

arrayand类型object也可以与非单个元字段一起使用。例如,如果之前的“发布”元键设置singlefalse,则可以接受以下 JSON 数据。

{
  "meta": {
    "release": [
      {
        "version": "5.2",
        "artist": "Jaco"
      },
      {
        "version": "5.1",
        "artist": "Betty"
      }
    ]
  }
}

这将导致两个元数据库行。第一个包含{ "version": "5.2", "artist": "Jaco" },第二个包含{ "version": "5.1", "artist": "Betty" }.

同样,如果“projects”示例设置为 ,则以下数据将被single接受false

{
  "meta": {
    "projects": [
      [
        "WordPress",
        "BuddyPress"
      ],
      [
        "bbPress"
      ]
    ]
  }
}

这将导致两个元数据库行。第一个包含[ "WordPress", "BuddyPress" ],第二个包含[ "bbPress" ].

无效的存储值

如果元字段的现有值未根据注册的类型和模式进行验证,则该元字段的值将返回为 null。如果在执行更新请求时将该空值传回 API,您将收到rest_invalid_stored_value错误消息:The %s property has an invalid stored value, and cannot be updated to null.。要解决此问题,请使用有效值更新元键或从您的请求中省略该属性。

默认元数据值

如果没有定义值,WordPress 5.5 增加了对为元数据指定默认值的官方支持。例如,使用此代码片段,如果值尚未设置,price元字段将在 REST API 响应中设置为。0.00

register_post_meta(
     'product',
     'price',
     array(
         'single'  => true,
         'type'    => 'string',
         'default' => '0.00',
     )
 );

添加链接到 API 响应

WordPress 生成与查询资源关联的链接列表,以便更轻松地导航到相关资源。

{
 "_links": {
    "self": [
      {
        "href": "https://make.wordpress.org/core/wp-json/wp/v2/posts/28312"
      }
    ],
    "collection": [
      {
        "href": "https://make.wordpress.org/core/wp-json/wp/v2/posts"
      }
    ],
    "author": [
      {
        "embeddable": true,
        "href": "https://make.wordpress.org/core/wp-json/wp/v2/users/8670591"
      }
    ],
    "replies": [
      {
        "embeddable": true,
        "href": "https://make.wordpress.org/core/wp-json/wp/v2/comments?post=28312"
      }
    ],
    "wp:term": [
      {
        "taxonomy": "category",
        "embeddable": true,
        "href": "https://make.wordpress.org/core/wp-json/wp/v2/categories?post=28312"
      },
      {
        "taxonomy": "post_tag",
        "embeddable": true,
        "href": "https://make.wordpress.org/core/wp-json/wp/v2/tags?post=28312"
      }
    ]
  }
}

来自 Make.WordPress.org 帖子的链接示例

虽然这些链接将出现_links在 JSON 响应对象的属性下,但它并未存储WP_REST_Response::$dataWP_REST_Response::get_data(). 相反,服务器将在回显响应数据之前将链接数据附加到响应中。

可以使用 方法将自定义链接添加到响应中WP_REST_Response::add_link()。此方法接受三个参数,链接关系、URL 和可选的链接属性列表。例如,添加authorwp:term链接。

<?php
$response->add_link( 'author', rest_url( "/wp/v2/users/{$post->post_author}" ) );

$response->add_link( 'https://api.w.org/term', add_query_arg( 'post', $post->ID, rest_url( "/wp/v2/{$tax_base}" ) ) );

链接关系必须是来自 IANA 的已注册链接关系或受您控制的 URI。

author是一个注册的链接关系,描述为“上下文的作者”,我们用它来指向写帖子的 WordPress 用户。不存在描述与帖子关联的术语的链接关系,因此 WordPress 使用 URL https://api.w.org/termwp:term这在使用 CURIE 生成响应时转换为。

第三个参数add_link()是自定义属性列表。该embeddable属性可用于包含_embedded在使用查询参数时出现在响应部分的链接资源_embed。如果添加了具有相同关系的多个链接,则嵌入的响应将按照添加链接的顺序排列。

<?php
$response->add_link( 'author', rest_url( "/wp/v2/users/{$post->post_author}" ), array(
    'embeddable' => true,
) );
$response->add_link( 'author', rest_url( "/wp/v2/users/{$additional_author}" ), array(
    'embeddable' => true,
) );

链接到多作者帖子的示例实现。

{
  "_links": {
    "author": [
      {
        "embeddable": true,
        "href": "https://yourwebsite.com/wp-json/wp/v2/users/1"
      },
      {
        "embeddable": true,
        "href": "https://yourwebsite.com/wp-json/wp/v2/users/2"
      }
    ]
  },
  "_embedded": {
    "author": [
      {
        "id": 1,
        "name": "Primary Author"
      },
      {
        "id": 2,
        "name": "Secondary Author"
      }
    ]
  }
}

添加的订单链接被维护。

注册居里

WordPress 4.5 版引入了对 Compact URI 或 CURIE 的支持。这使得通过比可能很长的完整 URL 简单得多的标识符来引用链接成为可能。

CURIE 是使用rest_response_link_curies过滤器注册的。例如。

<?php
function my_plugin_prefix_register_curie( $curies ) {

    $curies[] = array(
        'name'      => 'my_plugin',
        'href'      => 'https://api.mypluginurl.com/{rel}',
        'templated' => true,
    );

    return $curies;
}

这会将API 响应中的链接 URL 从 转换https://api.mypluginurl.com/my_link为。my_plugin:my_link使用 添加链接时仍必须使用完整的 URL WP_REST_Response::add_link