WP_REST_Controller メソッド後編 追加フィールド

API Fetch について
WordPressのブロック開発メモ その11 REST API へのアクセス

基本的な REST API
WordPressでREST APIを使う前編
WordPressでREST APIを使う後編 REST APIの登録と REST コントローラ

REST API コントローラの実装
WP_REST_Controller メソッド前編
(σ・ω・)σ WP_REST_Controller メソッド後編 追加フィールド
WordPress REST API Controllerを実装してみる。

追加フィールド

WordPressのREST APIについて知っている必要があります。
例えば投稿を取得する場合、フィールドには投稿IDやタイトル、更新日などのフィールドが存在します。
これらフィールドに後付けで独自のフィールドを追加できるのが「追加フィールド」です。
追加フィールドの設定はregister_rest_field()関数を使います。

さらにmetaフィールドにメタキーを後付けで追加する方法もあります。
今回は追加フィールドの方についてです。

WP_REST_Controllerにはメタフィールドのためのメソッドがいくつか含まれてます。

protected function get_object_type()

スキーマ設定の中からオブジェクトタイプを取得します。

add_action('rest_api_init', function(){

    $controller = new class extends WP_REST_Controller
    {

        public function myExec()
        {
            $objectType = $this->get_object_type();
            echo $objectType;
        }

        public function get_item_schema()
        {
            return [
                '$schema' => 'http://json-schema.org/draft-04/schema#',

                // ここが取得される
                'title' => 'kurage',

                // ...略
            ];
        }

    };

    $controller->myExec();
});
kurage

get_item_schema()から得たスキーマからtitleの項目があれば取得する。
今回の例ではkurageを取得できます。

protected function get_additional_fields( $object_type = null )

register_rest_field()で登録した属性の一覧を取得する。
このメソッドの第一引数(オブジェクトタイプ)とregister_rest_field()の第一引数は合わせる。

add_action('rest_api_init', function(){

    register_rest_field(
        'kurage',
        'ikasan',
        [
            'get_callback' => fn() => '墨はくどー',
            'update_callback' => fn($value) => null
        ]
    );

    register_rest_field(
        'kurage',
        'takosan',
        [
            'get_callback' => fn() => 'タコ殴りだべー!',
            'update_callback' => fn($value) => null
        ]
    );

    $controller = new class extends WP_REST_Controller
    {

        public function myExec()
        {
            echo "<pre>";

            // ここの値
            $fields = $this->get_additional_fields('kurage');
        }

        public function get_item_schema()
        {
            return [
                '$schema' => 'http://json-schema.org/draft-04/schema#',
                'title' => 'kurage',

                // ...略
            ];
        }

    };

    $controller->myExec();
});

追加フィールド(名前はkurage)の属性一覧「ikasan, takosan」が取得されているのが確認できる。

  • 今回はkurageを渡したが、引数が無ければ$this->get_pbject_type()から取得される。

protected function add_additional_fields_schema( $schema )

今まで$this->get_items_schema()内で使用してきたメソッドです。

アイテムのフィールドに追加フィールド(register_rest_field()でスキーマ設定したもの)をマージして返します。
引数のスキーマにtitleプロパティがあり、追加フィールドの設定でschemaプロパティがあれば、それを$schema['properties]にマージして返します。

add_action('rest_api_init', function(){

    register_rest_field(
        'kurage',
        'ikasan',
        [
            'get_callback' => fn() => '墨はくどー',
            'update_callback' => fn($value) => null,

            // ここにschemaを設定していると、add_additional_fields_schema()を呼び出した時にマージされる。
            'schema' =>
            [
                'description' => 'I have 10 legs.',
                'type' => 'string'
            ]
        ]
    );

    register_rest_field(
        'kurage',
        'takosan',
        [
            'get_callback' => fn() => 'タコ殴りだべー!',
            'update_callback' => fn($value) => null
        ]
    );

    $controller = new class extends WP_REST_Controller
    {

        public function myExec()
        {
            $schema = [
                '$schema' => 'http://json-schema.org/draft-04/schema#',
                'title' => 'kurage',
                'type' => 'object',
                'properties' => [
                    'uni' => [
                        'description' => 'toge toge',
                        'type' => ['string', 'null']
                    ],
                    'kame' => [
                        'description' => 'noko noko',
                        'type' => ['string', 'null'],
                    ]
                ]
            ];

            // ここの値
            $newSchema = $this->add_additional_fields_schema($schema);

        }

    };

    $controller->myExec();
});

$this->add_additional_fields_schema()に渡すスキーマと、その戻り値のスキーマの違いをしらべます。

  • $schemaの値

  • $newSchemaの値

register_rest_field()で指定した追加フィールドのikasanがスキーマに追加されていることがわかる。

以下のように、

register_rest_field('kurage', 'ikasan', [ 'schema' => [...] ])

第三引数にschemaプロパティを追加すると、
それが$newSchema['properties][ikasan]に追加されることがわかる。

コードを簡素化して書くと以下のようになります(実際のコードと違います)。

protected function add_additional_fields_schema( $schema )
{
    $fields = $this->get_additional_fields( $schema['title'] );

    foreach($fields as $k => $v)
    {
        if($v['schema'])
        {
            $schema['properties'][$k] = $v['schema'];
        }
    }

    return $schema;
}

protected function update_additional_fields_for_object( $data_object, $request )

アイテムの保存&更新の時、一緒に追加フィールド一覧を更新するようにします。
具体的にはregister_rest_field()で設定したupdate_callbackを実行します。

なのでcreate_item()update_item()から呼び出します。

内部のコードを簡素化すると次のようになります(実際のコードと違います)。

protected function update_additional_fields_for_object( $data_object, $request )
{
    $fields = $this->get_additional_fields();

    foreach( $fields as $fn => $option)
    {
        call_user_cunc(
            $option['update_callback'],
            $request[$fn],
            $data_object,
            $fn,
            $request,
            $this->get_object_type()
        );
    }
}

protected function add_additional_fields_to_object( $response_data, $request )

アイテムの取得時、一緒に追加フィールド一覧からデータを取得し、第一引数にマージして返します。
具体的にはregister_rest_field()で設定したget_callbackを実行します。

prepare_item_for_response()から呼び出します。

内部のコードを簡素化すると次のようになります(実際のコードと違います)。

protected function add_additional_fields_to_object( $response_data, $request )
{
    $fields = $this->get_additional_fields();

    foreach($fields as $fn => $options)
    {
        $response_data[$fn] = call_user_func(
            $options['get_callback'],
            // ... 略
        );
    }

    return $response_data;
}

実際には $this->get_fields_for_response()でフィルタリングします。

public function get_item_schema()

スキーマを$this->get_item_schema()で作成しますが、
WordPress本体の実装(WP_REST_Controllerの派生クラス)では

  • スキーマはキャッシュする
  • $this->add_additional_fields_schema()で追加フィールドをマージする

という実装のされかたをしてます。

add_action('rest_api_init', function(){

    $controller = new class extends WP_REST_Controller
    {
        public function get_item_schema()
        {
            if( $this->schema )
            {
                return $this->add_additional_fields_schema($this->schema);
            }

            $schema = [
                '$schema' => 'http://json-schema.org/draft-04/schema#',
                'title' => 'kurage',
                'type' => 'object',
                'properties' => [
                    'uni' => [
                        'description' => 'toge toge',
                        'type' => ['string', 'null']
                    ],
                    'kame' => [
                        'description' => 'noko noko',
                        'type' => ['string', 'null'],
                    ]
                ]
            ];

            $this->schema = $schema;
            return $this->add_additional_fields_schema($this->schema);
        }
    };

    $controller->myExec();
    exit;

});
add_action('rest_api_init', function(){

    register_rest_field(
        'kurage',
        'ikasan',
        [
            'get_callback' => fn() => '墨はくどー',
            'update_callback' => fn($value) => null,

            // ここにschemaを設定していると、add_additional_fields_schema()を呼び出した時にマージされる。
            'schema' =>
            [
                'description' => 'I have 10 legs.',
                'type' => 'string'
            ]
        ]
    );

    register_rest_field(
        'kurage',
        'takosan',
        [
            'get_callback' => fn() => 'タコ殴りだべー!',
            'update_callback' => fn($value) => null
        ]
    );

    $controller = new class extends WP_REST_Controller
    {

        public function myExec()
        {
            // ここの値
            $schema = $this->get_item_schema();

        }

        public function get_item_schema()
        {
            $this->schema = $this->schema ?? [
                '$schema' => 'http://json-schema.org/draft-04/schema#',
                'title' => 'kurage',
                'type' => 'object',
                'properties' => [
                    'uni' => [
                        'description' => 'toge toge',
                        'type' => ['string', 'null']
                    ],
                    'kame' => [
                        'description' => 'noko noko',
                        'type' => ['string', 'null'],
                    ]
                ]
            ];

            return $this->add_additional_fields_schema($this->schema);
        }

    };

    $controller->myExec();
    exit;

});
  • get_item_schema()の実装コードを見やすいよう書き直してます。

スキーマの値と、追加フィールドがマージされた値を返すように実装してます。
作成されたスキーマの結果を見て確認できます。

certificate Docker Gutenberg Hyper-V openssl PHP React ReduxToolkit REST ubuntu WordPress オレオレ認証局 フレームワーク