タイトル: $_GET
SEOタイトル: PHP $_GET スーパーグローバル変数完全ガイド(XSS / SQL Injection 対策・$_POST との違い)
| この記事の要点 |
|
$_GET の基本
PHP の$_GET は、URL のクエリストリング(?key=value&key2=value2)から渡された値を受け取るためのスーパーグローバル連想配列です。フォームを method="GET" で送信したとき、または直接 URL にパラメータを付けたときに自動で埋まります。

基本的な使い方
taro [age] => 20 )
フォームから $_GET に送る
';
echo 'カテゴリ: ' . htmlspecialchars($category);
セキュリティ: 必ずやること
$_GET の値はすべて信用してはいけません。URL は誰でも書き換えられるため、検証とエスケープを必ず行います。
XSS 対策(HTML 出力時)
タグを埋め込まれる可能性
echo 'こんにちは ' . $name;
// ✅ HTML エスケープ
echo 'こんにちは ' . htmlspecialchars($name, ENT_QUOTES, 'UTF-8');
// ❌ 古い書き方は ENT_QUOTES 必須
echo htmlspecialchars($name); // ' をエスケープしない設定があり危険
// ✅ ショートカット関数を作る
function h(string $s): string {
return htmlspecialchars($s, ENT_QUOTES | ENT_HTML5, 'UTF-8');
}
echo 'こんにちは ' . h($name);
SQL Injection 対策(DB クエリ時)
prepare('SELECT * FROM users WHERE id = :id');
$stmt->execute([':id' => $_GET['id']]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
// ✅ mysqli の場合
$mysqli = new mysqli('localhost', 'user', 'pass', 'app');
$stmt = $mysqli->prepare('SELECT * FROM users WHERE id = ?');
$stmt->bind_param('i', $_GET['id']); // 'i' = integer
$stmt->execute();
型検証とサニタイズ
$_GET vs $_POST vs $_REQUEST
| 変数 | 送信元 | URL に露出 | 主な用途 |
|---|---|---|---|
| $_GET | URL クエリ ?key=value | ★ する | 検索 / フィルター / パーマリンク |
| $_POST | リクエストボディ (form / JSON) | しない | ログイン / 登録 / 機密データ |
| $_REQUEST | $_GET + $_POST + $_COOKIE | — | 非推奨。明示的に GET/POST を使う |
| $_FILES | multipart/form-data の添付 | — | ファイルアップロード |
使い分け:
- 検索結果ページのようにURL を共有・ブックマークさせたい → $_GET
- パスワード / 個人情報 / 大きいデータ → 必ず $_POST(URL に出ない)
- RESTful API では GET=取得 / POST=作成 / PUT=更新 / DELETE=削除 と動詞を分ける
URL エンコーディング
URL に直接書けない文字(日本語 / スペース / & / # など)はURL エンコードします。$_GET はデコード済みの値を返します。
'太郎', 'age' => 25, 'city' => '東京'];
$url = '/page.php?' . http_build_query($params);
// /page.php?name=%E5%A4%AA%E9%83%8E&age=25&city=%E6%9D%B1%E4%BA%AC
配列パラメータ
1 [1] => 2 [2] => 3 )
// URL: /page.php?user[name]=taro&user[age]=20
print_r($_GET['user']);
// Array ( [name] => taro [age] => 20 )
// チェックボックスを配列で受け取る
//
//
$tags = $_GET['tags'] ?? [];
foreach ($tags as $tag) {
echo h($tag) . ' ';
}
Laravel での同等処理
input('keyword'); // 推奨
$keyword = $request->query('keyword'); // GET のみに限定
$keyword = $request->get('keyword'); // input のエイリアス
// 配列
$ids = $request->input('ids', []); // [1, 2, 3]
// バリデーション
$validated = $request->validate([
'keyword' => 'required|string|max:100',
'page' => 'integer|min:1',
]);
return view('search', $validated);
}
$_GET の長さ制限
- URL 全体の長さはブラウザ / サーバが個別に制限。実務上の上限は 2,000 バイト前後
- Apache:
LimitRequestLine既定 8190 バイト - Nginx:
large_client_header_buffers既定 8K - 長くなる場合は $_POST に変更するか、ID を渡してサーバ側で展開
FAQ
Q: $_GET の値はすべて文字列?
A: はい。数字も文字列として届きます。整数比較したいときは (int)$_GET["age"] でキャストするか filter_input(INPUT_GET, "age", FILTER_VALIDATE_INT)。
Q: GET でログインフォームを作るのは?
A: 絶対 NG。URL にパスワードが残り、履歴・アクセスログに出ます。ログインは必ず POST + HTTPS。
Q: $_GET と filter_input どちらを使う?
A: 単純な取得は $_GET、型検証・サニタイズを兼ねたいなら filter_input。バリデーション込みなら Laravel の Request 推奨。