レスポンスの変更
TOPICS
翻訳元記事はこちらです。
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
よりもずっとシンプルですが、ひとつ注意点があります。
WordPress 4.9.8以前では、register_meta
を使ってshow_in_rest
に設定したメタフィールドは、指定されたタイプのすべてのオブジェクトに登録されていました。1つのカスタム投稿タイプがメタフィールドを表示すると、すべてのカスタム投稿タイプがそのメタフィールドを表示します。WordPress 4.9.9.8では、特定の投稿タイプのメタキーの使用量を減らすために、object_subtype
引数でregister_meta
を使用することが可能になりました。
WordPress 5.3 より前のバージョンでは、register_meta
はスカラ値(文字列、整数、数値、ブール値)のみをサポートしていました。WordPress 5.3 では、オブジェクト型と配列型のサポートが追加されました。
APIのレスポンスにカスタムフィールドを追加する
register_rest_field
を使った方法
register_rest_field 関数は、REST API レスポンスオブジェクトにフィールドを追加する最も柔軟な方法です。これは3つのパラメータを受け付けます。
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
フィールドは存在しますが、コアでは使用されていないため、これは機能します。コメントカルマを実際に実装するには、別のエンドポイントを使う必要があることに注意してください。
これは基本的な例です。特定のフィールドに必要なパーミッションチェックやエラー処理を慎重に検討してください。
訳者注:register_rest_fieldの実例は、Qiitaの記事で紹介しているものがあるので、そちらも参考にしてみてください。
訳者注:コメントのカルマってなに?と思いましたが、値は常に0だそうです。
関数リファレス:get_comments
register_rest_field
はどのように機能するの?
グローバル変数$wp_rest_additional_fields
は、各オブジェクトタイプに追加するレスポンスフィールドを保持するために、REST APIインフラストラクチャによって内部的に使用されます。
REST API は、このグローバル変数に追加するためのユーティリティ関数として register_rest_field
を提供しています。グローバル変数に直接追加することは、前方互換性を確保するために避けなければなりません。
それぞれのオブジェクトタイプ – 投稿、ユーザー、ターム、コメントなど – $wp_rest_additional_fields
には、フィールドの値を取得または更新するために使用されるコールバックを含む、フィールド定義の配列が含まれています。
REST APIで登録されたメタ情報を扱う
register_meta 関数は、特定のオブジェクトタイプのメタフィールドを定義する際の処理を簡素化します。新しいメタキーを登録する際に 'show_in_rest' => true
を設定することで、そのキーに REST API からアクセスできるようになります。
postのレスポンスで、postのメタフィールドを読み書きする
<?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 );
この例では、投稿のメタフィールドの読み書きを許可する方法を示しています。これにより、このフィールドは wp-json/wp/v2/posts/<post-id>
への POST リクエストで更新されたり、 wp-json/wp/v2/posts/
への POST リクエストで投稿と一緒に作成されたりするようになります。
カスタム投稿タイプに登録されたメタフィールドについては、投稿タイプがカスタムフィールドをサポートしている必要があることに注意してください。そうでない場合、メタフィールドはREST APIに表示されません。
投稿タイプ固有のメタ情報
WordPress 4.9.8 では、register_post_meta
と register_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 );
register_post_metaのコードリファレンス
register_term_metaのコードリファレンス
オブジェクトメタタイプ
WordPress 5.3ではメタを登録する際にオブジェクト型を使用できるようになりました。重要なのは、object
は JSON オブジェクトを指し、これは PHP の連想配列と同等です。
オブジェクトメタを登録する際には、type
をobject
に設定するだけでは不十分で、どのようなプロパティを許可するかをWordPressにも伝える必要があります。これは、メタデータを登録する際にJSONスキーマを記述することで行います。
例えば、以下のコードサンプルでは、与えられたJSONデータを受け付ける “release “というポストメタフィールドを登録しています。
{
"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
ではなく配列になり、schema
キーにJson Schemaが指定されていることに注目してください。そして、各プロパティはプロパティ配列にリストされます。
最低限、各プロパティは型を指定しなければなりませんが、rest_validate_value_from_schema
が理解できるJSON Schemaキーワードも同様に使用できます。
追加のプロパティ
デフォルトでは、プロパティのリストは厳密なホワイトリストになっています。リストにないプロパティがリクエストで送信された場合、REST API はエラーを返します。
送信されたプロパティは、有効なプロパティではありません、のように。
事前にプロパティ名がわからない場合は、 additionalProperties
キーワードを使用することができます。例えば、additionalProperties
が数字であることを強制するには、以下のコードを使用できます。
{
"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はJSON配列を指し、これはPHPの数値配列と同等です。
配列メタを登録する際に、型を配列に設定するだけでは不十分なので、配列内の項目の期待される形式をWordPressに伝える必要があります。これは、メタデータを登録する際にJSON Schemaのエントリを記述することで行います。
この値を指定しなかった場合、register_meta
はfalse
を返し、次のような警告を発します。
REST APIで表示するメタタイプ「配列」を登録する際には、「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
ではなく配列になり、schema
キーにJSONスキーマが指定されていることに注目してください。
items
キーワードは、各配列のメンバーを検証するための JSON スキーマを定義するために使用されます。文字列のようなスカラー型やオブジェクトのような複雑な型を指定することができます。
例えば、以下の与えられた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',
),
),
),
),
),
)
);
配列型は、配列のキーが 0 から始まる連続した整数であることを強制します。 配列は array_values
を用いて再インデックス化されます。
単一でないメタデータ
単一ではないメタ・フィールドは、オブジェクトごとに1つの値ではなく、オブジェクトごとに値の配列を持ちます。これらの値はそれぞれメタテーブルの別の行に格納されます。
配列型とオブジェクト型は、シングルではないメタフィールドでも使用できます。例えば、先ほどの “release “メタキーにsingle
がfalse
に設定されていた場合、以下のようなJSONデータを受け付けることができます。
{
"meta": {
"release": [
{
"version": "5.2",
"artist": "Jaco"
},
{
"version": "5.1",
"artist": "Betty"
}
]
}
}
これにより、2つのメタデータベースの行が生成されます。
1つ目は、 { "version": "5.2", "artist": "Jaco" }
2つ目は、 { "version": "5.1", "artist": "Betty" }
同様に、”projects “の例では、single
をfalse
に設定した場合、以下のデータが受け入れられます。
{
"meta": {
"projects": [
[
"WordPress",
"BuddyPress"
],
[
"bbPress"
]
]
}
}
これにより、2つのメタデータベースの行が生成されます。
1つ目は、 [ "WordPress", "BuddyPress" ]
2つ目は、[ "bbPress" ]
無効な保存値
メタフィールドの既存の値が登録された型およびスキーマに対して検証されない場合、そのメタフィールドの値はnullとして返されます。
更新リクエストを行う際にその null 値が API に渡されると、rest_invalid_stored_value
エラーが発生します。
「○番目のプロパティは無効な値です。nulでは更新できません。」
これを修正するには、メタキーを有効な値で更新するか、リクエストからそのプロパティを省略してください。
リンクを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の投稿からのリンク例
これらのリンクは JSON レスポンスオブジェクトの _links
プロパティの下に表示されますが、WP_REST_Response::$data
には保存されず、WP_REST_Response::get_data()
でアクセスすることもできません。その代わり、サーバーはレスポンスデータをエコーする直前にリンクデータをレスポンスに追加します。
WP_REST_Response::add_link()
メソッドを使用して、カスタムリンクをレスポンスに追加することができます。このメソッドは、リンク関係、URL、オプションでリンク属性のリストの3つのパラメータを受け取ります。例えば、author
と wp: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ではhttps://api.w.org/term
のURLを使用しています。これをCURIE(Compact URIs)を使ってレスポンスを生成する際にwp:term
に変換しています。
add_link()
の 3 番目のパラメータは、カスタム属性のリストです。embeddable
属性を使用すると、_embed
クエリーパラメータを使用したときに、リンクされたリソースがレスポンスの_embedded
セクションに表示されることを含めることができます。同じリレーションで複数のリンクが追加された場合、埋め込まれたレスポンスはリンクが追加された順番と同じになります。
<?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"
}
]
}
}
リンクが追加された順番を維持しています。
CURIEの登録
WordPress のバージョン 4.5 では、Compact URIs、つまり CURIEs のサポートが導入されました。これにより、リンクを参照する際には、長くなりがちなフル 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
に変換します。WP_REST_Response::add_link
を使用してリンクを追加する場合でも、フル URL を使用する必要があります。