URLSearchParams に配列を渡すと文字列になる。WordPress REST APIではどう扱われる?
カンマ文字列と status[] を境界ごとに追う
JavaScript の配列 ['draft', 'publish'] を WordPress REST API の投稿一覧へ渡すため、URLSearchParams でクエリを作ります。
const statuses = ['draft', 'publish'];
const params = new URLSearchParams({
status: statuses,
});
console.log(params.toString());
// status=draft%2Cpublish
%2C はカンマなので、実質は status=draft,publish です。
2つの投稿状態を渡したかったのに、クエリパラメータは1つの文字列になりました。
PHP 側で配列として受け取れないなら、WordPress は draft と publish を正しく処理できないのでしょうか。
今回は、この疑問を JavaScript・PHP・WordPress の順に追い、実際の API の応答でも確認します。
目次
結論:WordPressではどちらの書式も使える
今回確認した WordPress REST API の投稿一覧 status では、次の2つの書式がどちらも使えました。
status=draft,publish
status[]=draft&status[]=publish
どちらも最終的には draft と publish の2状態として扱われます。
ただし、PHP に届いた時点では、それぞれ文字列と配列という異なる形になっています。
なぜ両方が動くのかを理解するには、途中でどのような変換が行われるかを見る必要があります。
そもそも、URL のクエリには JavaScript のような配列型がありません。
WHATWG URL Standard では、URLSearchParams は名前と値の組のリストとして定義されています。同じ名前を複数回使うこともできますが、それを配列として解釈するかどうかは受信側のルール次第です。
PHPでは文字列と配列に分かれる
まずは WordPress の手前にある PHP の処理を確認します。
配列をクエリで渡す方法として、カンマ区切り、角括弧付き、同じキーの繰り返しという3種類を比較します。
PHP 8.5.2 の parse_str() を使い、それぞれがどのように解釈されるかを調べました。
<?php
$cases = [
'comma' => 'status=draft,publish',
'brackets' => 'status[]=draft&status[]=publish',
'repeated' => 'status=draft&status=publish',
];
foreach ($cases as $label => $query) {
parse_str($query, $parsed);
echo $label, ': ', json_encode($parsed), PHP_EOL;
}
結果は次のとおりです。
comma: {"status":"draft,publish"}
brackets: {"status":["draft","publish"]}
repeated: {"status":"publish"}
| クエリ形式 | PHPでの解釈 |
|---|---|
status=draft,publish |
1つの文字列 |
status[]=draft&status[]=publish |
2要素の配列 |
status=draft&status=publish |
最後の値だけが残る |
カンマ形式は "draft,publish" という文字列のままです。一方、status[] 形式は2要素の配列になります。
角括弧が %5B%5D とパーセントエンコードされていても、PHP が解釈した結果は変わりません。
注意したいのは、角括弧なしで同じキーを繰り返す形式です。
status=draft&status=publish
この場合、PHP の parse_str() では前の値が上書きされ、"publish" だけが残ります。
draft という情報自体が失われるため、後続の WordPress の処理でも元の2状態には戻せません。
ここまでを見ると、PHP で最初から配列になる status[] 形式が正解に思えます。
しかし、PHP で受け取った値が、そのまま WordPress REST API の最終的な値になるわけではありません。
WordPressはカンマ文字列を配列に変換する
WordPress REST API の投稿一覧には、status の値を整える専用の処理があります。
PHP から渡されたカンマ文字列は、この処理によって投稿状態のリストに変換されます。
PHP
"draft,publish"
↓ WordPress がカンマで分割
['draft', 'publish']
つまり、URLSearchParams が配列を文字列にした時点では、まだ必要な情報は失われていません。
カンマと両方の状態名が残っているため、WordPress 側で2状態のリストとして扱えます。
WordPress Coreの処理を追う
WordPress Core のソースコードを確認すると、投稿一覧の status は次の処理を通ります。
WP_REST_Request::sanitize_params()
↓
WP_REST_Posts_Controller::sanitize_post_statuses()
↓
wp_parse_slug_list()
↓
wp_parse_list()
それぞれの役割は次のとおりです。
| 処理 | 役割 |
|---|---|
sanitize_params() |
登録された引数ごとのサニタイズ処理を呼び出す |
sanitize_post_statuses() |
投稿状態の一覧を整え、権限も検証する |
wp_parse_slug_list() |
値をスラッグとして整え、重複を除く |
wp_parse_list() |
文字列をカンマや空白で分割し、リストにする |
ここで重要なのが wp_parse_list() の挙動です。
この関数は、受け取った値が文字列か配列かによって処理を変えます。
| 入力 | 処理 |
|---|---|
"draft,publish" |
文字列なので、カンマで分割して配列にする |
['draft', 'publish'] |
すでに配列なので、要素を確認して配列のまま返す |
つまり、カンマ形式と status[] 形式では、同じ変換が行われているわけではありません。
文字列は分割され、配列は配列のまま処理されます。
異なる経路を通りながら、結果として同じ2要素のリストになる仕組みです。
なお、WordPress REST API には一般的な配列引数の検証・サニタイズ処理もありますが、今回の投稿一覧 status には、この専用処理が登録されています。
そのため、今回の結果をすべての配列パラメータに当てはめることはできません。
実サイトでも同じ結果になった
Core ソースの確認だけでなく、2026年9月24日に実サイトでも検証しました。
実サイトでは、2状態だけでなく複数の投稿状態を指定した場合も比較するため、次の4状態を使用しています。
draft
private
pending
publish
同じ認証、投稿者、投稿状態、並び順を使用し、クエリ形式だけを変えて GET リクエストを送信しました。
比較したのは次の2形式です。
status=draft,private,pending,publish
status[]=draft&status[]=private&status[]=pending&status[]=publish
検証結果は次のとおりです。
| 検証項目 | 結果 |
|---|---|
| HTTPステータス | 両形式とも200 |
| 全件取得 | 成功 |
| 投稿総数 | 一致 |
| 投稿IDの集合 | 一致 |
| 投稿IDの並び順 | 一致 |
両形式とも HTTP 200 を返し、取得した投稿の総件数、投稿IDの集合、並び順がすべて一致しました。
今回確認した実サイトでは、クエリ形式が異なっていても同じ投稿集合が返されています。
実際の投稿件数とIDは公開せず、比較結果のみを記録しています。また、実測時に WordPress のバージョンは取得していないため、単一環境・確認日時点の結果として扱います。
なお、draft や private などの投稿状態を取得できるかどうかは、認証やユーザーの権限にも依存します。今回の比較では、両形式で同じ認証条件を使用しています。
JavaScriptではどう書くべきか
今回の WordPress REST API の投稿一覧 status では、カンマ形式と status[] 形式のどちらも利用できます。
それぞれの JavaScript の書き方を確認します。
カンマ形式で渡す
冒頭で使用した URLSearchParams の書き方です。
const statuses = ['draft', 'publish'];
const params = new URLSearchParams({
status: statuses,
});
console.log(params.toString());
// status=draft%2Cpublish
JavaScript の配列が文字列化され、カンマ区切りの値として送信されます。
今回の WordPress status では、この文字列が後続の処理で分割されるため、2状態として扱われます。
status[]形式で渡す
PHP に届いた時点で配列として解釈させたい場合は、append() を使って同じ名前のパラメータを追加できます。
const statuses = ['draft', 'publish'];
const params = new URLSearchParams();
statuses.forEach(status => {
params.append('status[]', status);
});
console.log(params.toString());
// status%5B%5D=draft&status%5B%5D=publish
%5B と %5D は、それぞれ [ と ] がパーセントエンコードされたものです。
したがって、実質的には次のクエリになります。
status[]=draft&status[]=publish
この形式なら、PHP の parse_str() によって最初から2要素の配列として解釈されます。
3つの書式を比較する
| 書式 | 評価 |
|---|---|
status[]=draft&status[]=publish |
PHP 到達時点から配列として扱われる。複数値であることが明示的 |
status=draft,publish |
今回の WordPress status では利用可能。WordPress 側の分割処理に依存する |
status=draft&status=publish |
PHP では前の値が失われるため、この用途では避ける |
status[] は複数値を明示できる書式ですが、今回の WordPress status では唯一の正解ではありません。
既存コードの規約や中継サーバーの挙動、PHP 到達時点で配列として扱いたいかどうかを踏まえて選択できます。
ただし、ほかの REST API でも同じ形式が使えるとは限りません。
URL のクエリには配列の唯一の書式がなく、受信側によって解釈のルールが異なるためです。
途中のデータ形式だけで判断しない
今回の調査では、処理をどこまで追うかによって、見えてくる結論が変わりました。
- JavaScript では、配列がカンマ区切りの文字列に変換される
- PHP では、カンマ形式は文字列、
status[]形式は配列として解釈される - WordPress では、カンマ文字列も投稿状態のリストへ変換される
JavaScript の出力だけを見れば、配列が文字列になったことを問題だと考えるかもしれません。
PHP まで確認すれば、status[] 形式だけが正しく見えます。
しかし、WordPress の内部処理まで追うと、カンマ形式も正常に扱われることが分かります。
途中のデータ形式が想定と異なっていても、それだけで API 全体の動作が誤っているとは判断できません。
API の挙動を調べるときは、最終的なレスポンスだけでなく、必要に応じて値の形が変わる場所を確認すると原因を追いやすくなります。
今回なら、URLSearchParams が生成したクエリ、PHP が解釈した値、WordPress が処理した投稿状態のリストという3つの段階です。
配列が文字列になったこと自体が問題なのではなく、受信側がその文字列をどのように解釈するかが重要でした。
参考にした一次情報
- WP_REST_Posts_Controller::get_collection_params()(投稿一覧のパラメータ定義)
- WP_REST_Request::sanitize_params()(REST API の引数サニタイズ処理)
- WP_REST_Posts_Controller::sanitize_post_statuses()(投稿状態のサニタイズと権限検証)
- wp_parse_slug_list()(スラッグのリスト化と重複除去)
- wp_parse_list()(文字列と配列の処理の違い)
- rest_sanitize_value_from_schema()(REST API の一般的なスキーマサニタイズ処理)
- WHATWG URL Standard: URLSearchParams(名前と値の組、
append()の規則) - PHP Manual: parse_str()(クエリ文字列の解析と角括弧付きパラメータ)
- Node.js URL API: URLSearchParams(オブジェクトに含まれる配列値の文字列化)








