この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:5
ページ更新者:guest
更新日時:2026-06-11 07:12:00

タイトル: $_GET
SEOタイトル: PHP $_GET スーパーグローバル変数完全ガイド(XSS / SQL Injection 対策・$_POST との違い)

この記事の要点
  • $_GET は URL クエリパラメータを受け取る PHP のスーパーグローバル変数 (連想配列)
  • アクセス: $_GET["name"]、存在確認は isset($_GET["name"]) または $_GET["name"] ?? null
  • XSS 対策htmlspecialchars()SQL Injection 対策に Prepared Statement (PDO)
  • $_POST との違い: $_GET は URL に露出 → 検索系・パーマリンク向き、$_POST は本文 → 機密 / 大きいデータ向き
  • 配列パラメータ ?ids[]=1&ids[]=2$_GET["ids"] が配列になる。Laravel は $request->input("x")

$_GET の基本

PHP の$_GET は、URL のクエリストリング(?key=value&key2=value2)から渡された値を受け取るためのスーパーグローバル連想配列です。フォームを method="GET" で送信したとき、または直接 URL にパラメータを付けたときに自動で埋まります。

PHP $_GET の動作イメージ

基本的な使い方

<?php
// URL: https://example.com/page.php?name=taro&age=20

// 値の取得
$name = $_GET['name']; // 'taro'
$age  = $_GET['age'];  // '20' (文字列であることに注意)

// 未定義キーアクセス警告を回避 (PHP 7+)
$name = $_GET['name'] ?? '';

// 存在確認
if (isset($_GET['name'])) {
    echo 'こんにちは ' . $name . ' さん';
}

// 全件確認
print_r($_GET);
// Array ( [name] => taro [age] => 20 )

GET フォーム送信例

フォームから $_GET に送る

<!-- search.html -->
<form action="/search.php" method="GET">
    <input type="text" name="keyword" placeholder="検索キーワード">
    <select name="category">
        <option value="all">全て</option>
        <option value="news">ニュース</option>
        <option value="blog">ブログ</option>
    </select>
    <button type="submit">検索</button>
</form>

<!-- 送信後の URL: /search.php?keyword=PHP&category=news -->
<?php
// search.php
$keyword  = $_GET['keyword']  ?? '';
$category = $_GET['category'] ?? 'all';

echo 'キーワード: ' . htmlspecialchars($keyword) . '<br>';
echo 'カテゴリ: '  . htmlspecialchars($category);

セキュリティ: 必ずやること

$_GET の値はすべて信用してはいけません。URL は誰でも書き換えられるため、検証とエスケープを必ず行います。

XSS 対策(HTML 出力時)

<?php
$name = $_GET['name'] ?? '';

// ❌ 危険: そのまま出力 → <script> タグを埋め込まれる可能性
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 クエリ時)

<?php
// ❌ 絶対やってはいけない: 文字列連結
$id = $_GET['id'];
$sql = "SELECT * FROM users WHERE id = $id"; // ?id=1 OR 1=1 で全件流出

// ✅ PDO の Prepared Statement
$pdo = new PDO('mysql:host=localhost;dbname=app', 'user', 'pass');
$stmt = $pdo->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();

型検証とサニタイズ

<?php
// filter_input でフィルタリング
$id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
if ($id === false || $id === null) {
    die('id is required and must be int');
}

// メール形式チェック
$email = filter_input(INPUT_GET, 'email', FILTER_VALIDATE_EMAIL);

// URL 形式チェック
$url = filter_input(INPUT_GET, 'url', FILTER_VALIDATE_URL);

// 文字列のサニタイズ (PHP 8.1+ では SANITIZE_STRING は非推奨)
// → htmlspecialchars / strip_tags を明示的に使う
$name = strip_tags($_GET['name'] ?? '');
$name = htmlspecialchars($name, ENT_QUOTES, 'UTF-8');

$_GET vs $_POST vs $_REQUEST

変数送信元URL に露出主な用途
$_GETURL クエリ ?key=value★ する検索 / フィルター / パーマリンク
$_POSTリクエストボディ (form / JSON)しないログイン / 登録 / 機密データ
$_REQUEST$_GET + $_POST + $_COOKIE非推奨。明示的に GET/POST を使う
$_FILESmultipart/form-data の添付ファイルアップロード

使い分け:

  • 検索結果ページのようにURL を共有・ブックマークさせたい → $_GET
  • パスワード / 個人情報 / 大きいデータ → 必ず $_POST(URL に出ない)
  • RESTful API では GET=取得 / POST=作成 / PUT=更新 / DELETE=削除 と動詞を分ける

URL エンコーディング

URL に直接書けない文字(日本語 / スペース / & / # など)はURL エンコードします。$_GET はデコード済みの値を返します。

<?php
// 送信側で URL を作る
$keyword = '東京 PHP & MySQL';
$url = '/search.php?keyword=' . urlencode($keyword);
// /search.php?keyword=%E6%9D%B1%E4%BA%AC+PHP+%26+MySQL

// 受信側 ($_GET) は自動デコード
$keyword = $_GET['keyword']; // '東京 PHP & MySQL'

// 複数パラメータをまとめる
$params = ['name' => '太郎', '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

配列パラメータ

<?php
// URL: /page.php?ids[]=1&ids[]=2&ids[]=3
print_r($_GET['ids']);
// Array ( [0] => 1 [1] => 2 [2] => 3 )

// URL: /page.php?user[name]=taro&user[age]=20
print_r($_GET['user']);
// Array ( [name] => taro [age] => 20 )

// チェックボックスを配列で受け取る
// <input type="checkbox" name="tags[]" value="php">
// <input type="checkbox" name="tags[]" value="js">
$tags = $_GET['tags'] ?? [];
foreach ($tags as $tag) {
    echo h($tag) . ' ';
}

Laravel での同等処理

<?php
// Laravel Controller
public function search(Request $request)
{
    // GET ?keyword=PHP
    $keyword = $request->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[&quot;age&quot;] でキャストするか filter_input(INPUT_GET, &quot;age&quot;, FILTER_VALIDATE_INT)

Q: GET でログインフォームを作るのは?
A: 絶対 NG。URL にパスワードが残り、履歴・アクセスログに出ます。ログインは必ず POST + HTTPS。

Q: $_GET と filter_input どちらを使う?
A: 単純な取得は $_GET、型検証・サニタイズを兼ねたいなら filter_input。バリデーション込みなら Laravel の Request 推奨。