WP_REST_Request の get_param と get_json_params の違い|取得順序

結論

REST API のコールバックでは、引数 $request(WP_REST_Request)からパラメータを取ります。基本は $request->get_param( 'name' ) で十分ですが、取得元の違いを理解しておかないと、同名のパラメータが複数ある場合に意図しない値を拾います。

  • get_param() は、複数の取得元から優先順位に従って1つの値を返す
  • get_json_params() は JSON ボディだけ、get_query_params() は URL クエリだけ、get_url_params() はルートの正規表現で取った部分だけ
  • 検証とサニタイズは、register_rest_route() の args で宣言する
  • permission_callback は必ず設定する(公開APIでも __return_true を明示)

原因・仕組み

公式リファレンスによると、WP_REST_Request は get_param() で次の順に探します。

  1. JSON ボディ(Content-Type が JSON のとき)
  2. POST などのボディ
  3. GET のクエリ文字列
  4. URL(ルート)のパラメータ
  5. 既定値

同じ名前の値が複数の場所にあるときは、先に見つかったものが使われます。また、公式リファレンスには、HTTPメソッドが違っても同名の引数は区別しない、と書かれています。区別したいときは、メソッド別のゲッターを使います。

手順(サンプルコード)

add_action( 'rest_api_init', function () {
    register_rest_route( 'ks/v1', '/items/(?P<id>d+)', array(
        'methods'             => WP_REST_Server::EDITABLE,
        'permission_callback' => function () {
            return current_user_can( 'edit_posts' );
        },
        'args'                => array(
            'id'    => array(
                'validate_callback' => function ( $v ) { return is_numeric( $v ); },
            ),
            'title' => array(
                'type'              => 'string',
                'required'          => true,
                'sanitize_callback' => 'sanitize_text_field',
                'validate_callback' => function ( $v ) {
                    return is_string( $v ) && strlen( $v ) <= 20;
                },
            ),
            'qty'   => array( 'type' => 'integer', 'default' => 1 ),
        ),
        'callback'            => function ( WP_REST_Request $request ) {
            return rest_ensure_response( array(
                'id'    => $request->get_param( 'id' ),
                'title' => $request->get_param( 'title' ),
                'qty'   => $request->get_param( 'qty' ),
                'json'  => $request->get_json_params(),
                'query' => $request->get_query_params(),
            ) );
        },
    ) );
} );

args で type・required・validate_callback・sanitize_callback・default を宣言しておくと、コールバックの前に検証と整形が済みます。検証に失敗した場合は WP_Error が返り、HTTP 400 になります。

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

WordPress 7.1.2(日本語)、PHP 8.2.12。管理者ユーザーで rest_do_request() により内部リクエストを実行しました(testswp-rest-request-get-param-priority.md に全文)。

確認内容 結果
JSON ボディの title が <b>from-json</b>、クエリの title が from-query のとき get_param(‘title’) from-json(HTML タグは sanitize_text_field で除去)
get_query_params() title=from-query が別に取得できた
get_json_params() title と qty が取得できた(qty は整数 3 に変換)
get_url_params() id=12
get_method() / get_route() POST / /ks/v1/items/12
get_header(‘content_type’) application/json
title なしのリクエスト 400、コード rest_missing_callback_param、「パラメータ不足: title」
21文字以上の title 400、コード rest_invalid_param
フォームボディ(set_body_params)の title、qty なし 200、qty の既定値 1、has_param(‘qty’) は true
未ログイン(ユーザー 0)でのアクセス 401、コード rest_forbidden

JSON ボディとクエリの両方に title があるとき、get_param() は JSON ボディの値を優先しました。公式リファレンスの優先順位と一致します。また、qty を送らなかったリクエストでも has_param(‘qty’) が true でした。既定値が設定されたパラメータは、has_param() で「送られたか」を判定できないことに注意が必要です。

WP_REST_Request の get_param と get_json_params の違いの注意点

  • sanitize_callback は検証(validate_callback)のあとに実行されます。検証側で生の値を見ることになります。
  • permission_callback を省略すると、WordPress 5.5 以降は警告が出ます。公開APIでも 'permission_callback' => '__return_true' を明示してください。
  • Cookie 認証の REST リクエストでは、nonce(X-WP-Nonce ヘッダー)が必要です。未ログイン扱いになるときは、まず nonce を疑います。
  • 出力に含める値は、保存時ではなく表示時にエスケープします。

WP_REST_Request の get_param と get_json_params の違いでよくあるミス

  • $_POST や $_GET を直接読み、検証・サニタイズを飛ばす。
  • 同名のクエリとボディの値が混在し、意図しない値が使われる。
  • required を付けずに、欠けたパラメータで処理が進む。
  • permission_callback を __return_true にしたまま、更新系のAPIを公開する。

WP_REST_Request の get_param と get_json_params の違いのチェックリスト

  • ルートの args に type と検証関数を宣言したか。
  • 更新系の permission_callback で current_user_can() を確認しているか。
  • 取得元を限定したいときにメソッド別のゲッターを使っているか。
  • エラーは WP_Error で、status を付けて返しているか(WP_Error の扱い方)。

WP_REST_Request の get_param と get_json_params の違いのFAQ(よくある質問)

Q. get_param() と $request[‘title’] の違いは。
A. WP_REST_Request は ArrayAccess を実装しており、配列アクセスでも同じ動作になります。コードの読みやすさで選んで構いません。

Q. JSON のネストした値を取るには。
A. get_json_params() の配列を辿ります。

Q. ファイルのアップロードは。
A. get_file_params() を使います。このページの検証では扱っていません。

筆者の見解(WP_REST_Request の get_param と get_json_params の違い)

私見では、REST のコールバックを書くときに最も効果が大きいのは、args で検証とサニタイズを宣言し、コールバックの中を「検証済みの値を使うだけ」にすることだと考えます。取得元の優先順位は、普段意識しなくても動きますが、同名パラメータが混在するクライアントを受けるときに効いてきます。

WP_REST_Request の get_param と get_json_params の違いの関連項目

出典(一次情報)

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