REST API カスタムエンドポイントの作り方|register_rest_route の書き方

結論

カスタムエンドポイントは、rest_api_init アクションの中で register_rest_route() を呼んで作ります。必須の要素は次の4つです。

  1. 名前空間(ks/v1 のように、プラグインやテーマ固有の名前+バージョン)。
  2. ルート(/items/(?P<id>d+) のように、正規表現でパラメータを定義)。
  3. methods と callback。
  4. permission_callback(公開なら __return_true、書き込みなら権限チェック)。

登録後は /wp-json/ks/v1/items/12 のような URL で呼べます(パーマリンクが基本設定なら ?rest_route=/ks/v1/items/12)。

原因・仕組み

REST API のリクエストは、WP_REST_Server がルートを照合し、permission_callback、引数の検証・サニタイズ、callback の順に処理します。公式リファレンスでは、ルート登録は rest_api_init の時点か、それ以降に行うこと、名前空間の先頭と末尾にスラッシュを付けないこと、permission_callback は必須であること(5.5.0 以降)が示されています。コールバックの戻り値は、配列やオブジェクトでも rest_ensure_response() を通して WP_REST_Response として扱われ、WP_Error を返すとエラー応答になります。

手順(サンプルコード)

投稿IDから公開記事のタイトルを返す GET と、編集者以上が使える POST の例です。

add_action( 'rest_api_init', function () {
    register_rest_route( 'ks/v1', '/items/(?P<id>d+)', array(
        'methods'             => WP_REST_Server::READABLE,
        'callback'            => function ( WP_REST_Request $request ) {
            $post = get_post( (int) $request['id'] );
            if ( ! $post || 'publish' !== $post->post_status ) {
                return new WP_Error( 'ks_not_found', '記事が見つかりません', array( 'status' => 404 ) );
            }
            return rest_ensure_response( array( 'id' => $post->ID, 'title' => get_the_title( $post ) ) );
        },
        'permission_callback' => '__return_true', // 公開データなので全員に許可
        'args'                => array(
            'id' => array( 'validate_callback' => function ( $v ) { return is_numeric( $v ) && (int) $v > 0; } ),
        ),
    ) );

    register_rest_route( 'ks/v1', '/notes', array(
        'methods'             => WP_REST_Server::CREATABLE,
        'callback'            => function ( WP_REST_Request $request ) {
            return new WP_REST_Response( array( 'saved' => $request->get_param( 'text' ) ), 201 );
        },
        'permission_callback' => function () { return current_user_can( 'edit_posts' ); },
        'args'                => array(
            'text' => array( 'required' => true, 'sanitize_callback' => 'sanitize_text_field' ),
        ),
    ) );
} );

フロントエンドから呼ぶときは、ログイン中のユーザーとして書き込むなら X-WP-Nonce ヘッダーに wp_create_nonce( 'wp_rest' ) の値を付けます。

fetch( ksRest.root + 'ks/v1/notes', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', 'X-WP-Nonce': ksRest.nonce },
    body: JSON.stringify( { text: 'メモ' } ),
} );

動作確認(検証環境と結果)

WordPress 7.1.2、PHP 8.2.12、MariaDB 10.4.32 で、rest_do_request() を使い、HTTP を介さずサーバー内でリクエストを再現しました(実行: php C:Tempwp-testrun.php rest-api-custom-endpoint-how-to.php)。

リクエスト ステータス 応答
GET /ks/v1/items/(公開記事のID) 200 {"id":6,"title":"テスト記事"}
GET /ks/v1/items/999999 404 ks_not_found(自作の WP_Error)
GET /ks/v1/items/abc 404 rest_no_route(正規表現 d+ に一致せず)
POST /ks/v1/notes(管理者、text は <b>hi</b> there) 201 {"saved":"hi there"}(タグが除去された)
POST /ks/v1/notes(text なし) 400 rest_missing_callback_param
POST /ks/v1/notes(未ログイン) 401 rest_forbidden

rest_url( 'ks/v1/items/1' ) は、パーマリンク未設定の状態では http://localhost/index.php?rest_route=/ks/v1/items/1 を、パーマリンクを /%postname%/ にした状態(レビュー時の再実行)では http://localhost/wp-json/ks/v1/items/1 を返しました。URL は文字列で組み立てず、rest_url() で取得するのが確実です。実際のネットワーク越しの呼び出しと、Cookie+nonce 認証のブラウザ動作は、この環境では確認していません。

REST API カスタムエンドポイントの作り方の注意点

  • 名前空間はプラグインやテーマ固有にし、wp/v2 など core の名前空間は使いません。
  • permission_callback を省略すると、デバッグ通知が出ます(詳細はpermission_callback がない警告の対処)。
  • 認証が必要な書き込み系では、Cookie 認証なら nonce が必要です。アプリケーションパスワードを使う外部連携では、Basic 認証が使えます。
  • sanitize_callback は値を整える処理で、安全性の最終保証にはなりません。出力時のエスケープも別に行います。
  • 大量データを返す場合は、ページネーション用の引数(per_page など)を用意します。

REST API カスタムエンドポイントの作り方でよくあるミス

  • register_rest_route() を rest_api_init の外(functions.php の直下)で呼ぶ。
  • 名前空間を /ks/v1 のようにスラッシュ付きで書く。
  • 書き込み系の permission_callback に __return_true を指定して、誰でも書き込める状態にする。
  • 404 が返ったとき、ルートの正規表現が一致していないのに、パーマリンクの問題と誤解する(?rest_route=/ks/v1/... 形式でも試すと切り分けられます)。
  • コールバックで echo や wp_die() を使い、JSON が壊れる。戻り値で返す。

REST API カスタムエンドポイントの作り方のチェックリスト

  • rest_api_init の中で登録したか。
  • 名前空間にバージョンを含めたか。
  • permission_callback を、公開か権限チェックかで意図して書いたか。
  • 引数に validate_callback と sanitize_callback を付けたか。
  • 失敗時は WP_Error にステータスを入れたか。

REST API カスタムエンドポイントの作り方のFAQ(よくある質問)

Q. 既存の投稿タイプを REST に出すには?
A. register_post_type() の show_in_rest を true にします。独自エンドポイントは不要です。

Q. エンドポイントの一覧を確認する方法は?
A. /wp-json/ にアクセスすると、登録済みの名前空間とルートが見られます。

Q. admin-ajax.php との使い分けは?
A. 新規なら REST が扱いやすいです。既存の Ajax 資産の保守ではadmin-ajax.php が 0 や 400 を返す原因も参照してください。

筆者の見解(REST API カスタムエンドポイントの作り方)

REST のカスタムエンドポイントは、最初に「誰に許可するか」を permission_callback で決めてから、中身を書くのがよいと考えます。引数の検証を宣言的に書けるので、手動で $_POST を検査する Ajax より、抜け漏れを減らせます。一方で、小さな用途でも名前空間やバージョン管理が要るため、使い捨ての処理には少し大げさになる場面もあると思います。

REST API カスタムエンドポイントの作り方の関連項目

出典(一次情報)

タイトルとURLをコピーしました