16.

PHP URL パラメータの配列化完全ガイド($_GET / http_build_query / parse_str)

編集
この記事の要点
  • URL クエリで配列を渡す: ?ids[]=1&ids[]=2&ids[]=3$_GET["ids"] = [1, 2, 3]
  • 連想配列も可: ?user[name]=taro&user[age]=30$_GET["user"] = ["name"=>"taro", ...]
  • 配列 → URL クエリ: http_build_query(["ids" => [1,2,3]])ids%5B0%5D=1&ids%5B1%5D=2&ids%5B2%5D=3
  • URL クエリ文字列 → 配列: parse_str("ids[]=1&ids[]=2", $arr)
  • JS 側: URLSearchParamsFormData で同形式の送信が可
  • Laravel: $request->input("ids") で自動的に配列受取

基本: ?key[]=value で配列受取

PHP は URL クエリ文字列中の []配列要素として解釈します。

// URL: https://example.com/?ids[]=1&ids[]=2&ids[]=3

print_r($_GET);
/*
Array (
    [ids] => Array (
        [0] => 1
        [1] => 2
        [2] => 3
    )
)
*/

// 利用
foreach ($_GET['ids'] as $id) {
    echo $id;
}

連想配列([key] 形式)

// URL: ?user[name]=taro&user[age]=30&user[email]=taro@example.com

print_r($_GET);
/*
Array (
    [user] => Array (
        [name] => taro
        [age] => 30
        [email] => taro@example.com
    )
)
*/

// アクセス
$_GET['user']['name'];  // "taro"
$_GET['user']['age'];   // "30" (文字列)

多次元配列

// URL: ?cart[0][id]=10&cart[0][qty]=2&cart[1][id]=20&cart[1][qty]=1

print_r($_GET);
/*
Array (
    [cart] => Array (
        [0] => Array (
            [id] => 10
            [qty] => 2
        )
        [1] => Array (
            [id] => 20
            [qty] => 1
        )
    )
)
*/

// 利用
foreach ($_GET['cart'] as $item) {
    echo "ID: {$item['id']}, 数量: {$item['qty']}\n";
}

配列から URL クエリ生成: http_build_query()

$params = [
    'ids' => [1, 2, 3],
    'user' => [
        'name' => 'taro',
        'age' => 30,
    ],
    'lang' => 'ja',
];

echo http_build_query($params);
// ids%5B0%5D=1&ids%5B1%5D=2&ids%5B2%5D=3&user%5Bname%5D=taro&user%5Bage%5D=30&lang=ja

// URL デコードして見ると
// ids[0]=1&ids[1]=2&ids[2]=3&user[name]=taro&user[age]=30&lang=ja

// インデックス番号を入れない(連想配列のみ)
echo http_build_query($params, '', '&', PHP_QUERY_RFC3986);

// 区切り文字を変更
echo http_build_query($params, '', '&'); // HTML 中で使う際の安全化

// プレフィックス(インデックスが必要な場合の名前付け)
echo http_build_query(['filter' => [1, 2]], 'arg_');

RFC3986 vs RFC1738

エンコーディングスペース用途
PHP_QUERY_RFC1738(デフォルト)+application/x-www-form-urlencoded(フォーム送信)
PHP_QUERY_RFC3986%20URL 一般(パス / ハッシュ)
http_build_query(['q' => 'hello world']);
// "q=hello+world" (RFC1738)

http_build_query(['q' => 'hello world'], '', '&', PHP_QUERY_RFC3986);
// "q=hello%20world" (RFC3986)

URL クエリ文字列 → 配列: parse_str()

$qs = 'ids[]=1&ids[]=2&user[name]=taro&user[age]=30';

parse_str($qs, $result);

print_r($result);
/*
Array (
    [ids] => Array ( [0] => 1 [1] => 2 )
    [user] => Array ( [name] => taro [age] => 30 )
)
*/

// ❌ 第 2 引数省略は PHP 7.2+ で非推奨(グローバル汚染)
parse_str($qs);
echo $ids[0];  // 動くが非推奨

JavaScript 側で同形式を送る

URLSearchParams

const params = new URLSearchParams();
[1, 2, 3].forEach(id => params.append('ids[]', id));
params.append('user[name]', 'taro');
params.append('user[age]', 30);

console.log(params.toString());
// ids%5B%5D=1&ids%5B%5D=2&ids%5B%5D=3&user%5Bname%5D=taro&user%5Bage%5D=30

fetch('/api?' + params.toString());

jQuery $.param()

const data = {
    ids: [1, 2, 3],
    user: { name: 'taro', age: 30 }
};

console.log($.param(data));
// ids%5B%5D=1&ids%5B%5D=2&ids%5B%5D=3&user%5Bname%5D=taro&user%5Bage%5D=30

$.get('/api', data);

axios

import axios from 'axios';
import qs from 'qs';

// デフォルトでは ids: [1,2,3] が ids[]=1&ids[]=2 にならない
axios.get('/api', {
    params: { ids: [1, 2, 3] },
    paramsSerializer: params => qs.stringify(params, { arrayFormat: 'brackets' })
});
// → /api?ids[]=1&ids[]=2&ids[]=3

// arrayFormat オプション:
// 'indices' → ids[0]=1&ids[1]=2
// 'brackets' → ids[]=1&ids[]=2
// 'repeat'  → ids=1&ids=2
// 'comma'   → ids=1,2

POST フォームでの配列送信

GET と同じ書式が POST でも使えます。

<form action="/process" method="POST">
    <!-- チェックボックスで複数選択 -->
    <input type="checkbox" name="tags[]" value="php">    PHP
    <input type="checkbox" name="tags[]" value="js">     JS
    <input type="checkbox" name="tags[]" value="css">    CSS

    <!-- セレクトボックスの multiple -->
    <select name="langs[]" multiple>
        <option value="ja">日本語</option>
        <option value="en">英語</option>
    </select>

    <!-- 連想配列 -->
    <input type="text" name="user[name]" placeholder="名前">
    <input type="email" name="user[email]" placeholder="メール">

    <button>送信</button>
</form>
// 受信
print_r($_POST);
/*
Array (
    [tags] => Array ( [0] => php [1] => js )
    [langs] => Array ( [0] => ja )
    [user] => Array ( [name] => taro [email] => taro@example.com )
)
*/

Laravel での扱い

use Illuminate\Http\Request;

public function index(Request $request) {
    // GET /search?ids[]=1&ids[]=2&ids[]=3
    $ids = $request->input('ids');           // [1, 2, 3]
    $ids = $request->input('ids', []);       // デフォルト空配列

    // 連想配列
    $userName = $request->input('user.name'); // ドット記法
    $userAge  = $request->input('user.age');

    // バリデーション
    $validated = $request->validate([
        'ids'       => 'array|min:1',
        'ids.*'     => 'integer',         // 各要素のバリデーション
        'user.name' => 'required|string',
        'user.age'  => 'integer|min:0',
    ]);

    // クエリビルダで使う
    $users = User::whereIn('id', $ids)->get();
}

Postman での配列送信

方法記法
Query Params タブキーに ids[]、値に 1。複数行追加
URL に直接?ids[]=1&ids[]=2&ids[]=3
Body (form-data)キー ids[] を複数行
Body (raw JSON){"ids": [1, 2, 3]}(API がこちらを期待する場合)

JSON 形式で送る代替案

API として設計するなら、クエリ配列より JSON が現代的で型情報も明確:

// JS
fetch('/api/users', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
        ids: [1, 2, 3],
        user: { name: 'taro', age: 30 }
    })
});
// PHP 受信
$raw = file_get_contents('php://input');
$data = json_decode($raw, true);

print_r($data);
/*
Array (
    [ids] => Array ( [0] => 1 [1] => 2 [2] => 3 )
    [user] => Array ( [name] => taro [age] => 30 )
)
*/

// Laravel は自動で json デコード
$ids = $request->input('ids');

注意点・ハマりどころ

症状原因対処
配列が文字列で来る?ids=1,2,3 形式explode(',', $_GET['ids'])
URL が長すぎてエラーGET の URL 長制限 (2KB 〜)POST へ変更
max_input_vars 超過php.ini デフォルト 1000php.ini で増やす or 構造変更
ネスト深すぎで取得不能多次元配列の解釈JSON ボディに切替
?ids[]= 空文字空配列ではなく [''] になるarray_filter() で除去

セキュリティの注意

  • 受け取った配列は必ず型バリデーション(int / string / 範囲)
  • SQL に直接使わない → プリペアドステートメント + IN (?, ?, ?)
  • array_map('intval', $ids)整数強制もよくあるテクニック
  • 巨大配列でメモリ枯渇 DoScount() で件数上限チェック
// 安全な受け取り
$ids = $request->input('ids', []);
if (!is_array($ids) || count($ids) > 100) {
    abort(400, 'ids は最大 100 件');
}
$ids = array_values(array_unique(array_map('intval', $ids)));

// IN 句で使う
$users = User::whereIn('id', $ids)->get();

FAQ

Q: ?ids=1&ids=2 ([] 無し)で配列にできる?
A: PHP では後勝ち$_GET['ids'] = "2" になります。配列にするには [] 必須。Java/Spring 等は同名キーで自動配列化。

Q: URL が長くなりすぎる
A: 100 件超えるなら POST + JSON ボディに。またはカンマ区切り ?ids=1,2,3 + サーバ側で explode も実用的。

Q: max_input_vars 警告
A: 1000 個超のフォームフィールドで発生。php.inimax_input_vars = 5000 で緩和、またはJSON 化で根本解決。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. インストール方法
  2. 文法
  3. Composerのインストール
  4. 内部関数
  5. フレームワーク
  6. エラー一覧
  7. 改行出力
  8. printとechoの違い
  9. シングルクォートとダブルクォートの違い
  10. returnとyieldの違い
  11. var_dumpをログ出力
  12. CSV読み込み
  13. 待機・処理の遅延
  14. ログファイルにエラーを出力する方法
  15. エラーログ出力関数
  16. URLパラメータの配列化
  17. empty, is_null. issetの判定比較表
  18. httpステータスコードの付与
  19. バージョンの確認
  20. php.ini
  21. APIを呼び出す方法
  22. 外部ファイルを呼び出す方法
  23. カンマ区切りの文字列を配列に変換
  24. 配列からランダムに値を取り出す方法
  25. Webスクレイピング

最近更新/作成されたページ