PHPのスーパーグローバル変数とは、PHPがあらかじめ用意している特別な変数のことです。
通常、PHPでは関数の外で定義した変数を関数の中で使う場合、global を使ったり、引数として渡したりする必要があります。
しかし、スーパーグローバル変数は例外です。
関数の中、メソッドの中、クラスの中など、どのスコープからでもそのまま参照できます。
たとえば、次のように関数の中から $_SERVER を直接使えます。
function showRequestMethod() {
echo $_SERVER['REQUEST_METHOD'];
}
このように、global $_SERVER; のような宣言をしなくても使える点が、スーパーグローバル変数の大きな特徴です。
PHPで使える主なスーパーグローバル変数
PHPでよく使われるスーパーグローバル変数には、以下のようなものがあります。
| 変数名 | 主な役割 |
|---|---|
$GLOBALS | グローバルスコープの変数を参照する |
$_SERVER | サーバー情報やリクエスト情報を取得する |
$_GET | URLのクエリ文字列から値を取得する |
$_POST | POST送信されたフォームデータを取得する |
$_FILES | アップロードされたファイル情報を取得する |
$_COOKIE | Cookieの値を取得する |
$_SESSION | セッション情報を扱う |
$_REQUEST | GET・POST・COOKIE由来の値をまとめて扱う |
$_ENV | 環境変数を取得する |
スーパーグローバル変数は便利ですが、ユーザーが送信した値を含むものも多いため、使い方には注意が必要です。
特に、$_GET、$_POST、$_COOKIE、$_FILES、$_REQUEST は外部から送られてくる値を扱うため、基本的にそのまま信用してはいけません。
$GLOBALS
$GLOBALSとは
$GLOBALS は、グローバルスコープにある変数を参照するためのスーパーグローバル変数です。
たとえば、関数の外で定義した変数を、関数の中から参照したい場合に使えます。
$message = 'こんにちは';
function showMessage() {
echo $GLOBALS['message'];
}
showMessage();
このコードでは、関数の外にある $message を、関数内から $GLOBALS['message'] として参照しています。
通常、関数の外にある変数は、関数の中からそのまま使うことはできません。
$message = 'こんにちは';
function showMessage() {
echo $message; // そのままでは参照できない
}
このような場合に $GLOBALS を使うと、グローバル変数へアクセスできます。
$GLOBALSを使うときの注意点
$GLOBALS は便利ですが、実務では多用しない方がよいです。
理由は、どこからでもグローバル変数を書き換えられるため、コードの見通しが悪くなりやすいからです。
$count = 1;
function addCount() {
$GLOBALS['count']++;
}
addCount();
echo $count; // 2
小さなコードでは分かりやすく見えますが、規模が大きくなると「どこで値が変更されたのか」が追いにくくなります。
そのため、現在のPHP開発では、必要な値は関数の引数やクラスのプロパティとして渡す方が一般的です。
function addCount($count) {
return $count + 1;
}
$count = 1;
$count = addCount($count);
echo $count;
$GLOBALS は仕組みとして理解しておく必要はありますが、積極的に使う場面は多くありません。
$_SERVER
$_SERVERとは
$_SERVER は、サーバー情報やリクエスト情報を取得するためのスーパーグローバル変数です。
たとえば、アクセスされたURL、リクエストメソッド、ホスト名、ユーザーエージェント、IPアドレスなどの情報を取得できます。
よく使われるキーには、以下のようなものがあります。
| キー | 内容 |
|---|---|
$_SERVER['REQUEST_METHOD'] | リクエストメソッド |
$_SERVER['REQUEST_URI'] | リクエストされたURI |
$_SERVER['HTTP_HOST'] | ホスト名 |
$_SERVER['SERVER_NAME'] | サーバー名 |
$_SERVER['PHP_SELF'] | 実行中のスクリプト名 |
$_SERVER['HTTP_USER_AGENT'] | ブラウザやクライアント情報 |
$_SERVER['REMOTE_ADDR'] | アクセス元IPアドレス |
たとえば、フォームがPOST送信されたかどうかを判定する場合、次のように書けます。
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
echo 'POST送信されました';
}
$_SERVERのキーは必ず存在するとは限らない
$_SERVER の中身は、WebサーバーやPHPの実行環境によって変わります。
そのため、すべてのキーが常に存在するとは限りません。
特に、CLIでPHPを実行する場合や、サーバー設定が異なる場合には、期待したキーが存在しないことがあります。
そのため、実務では次のように存在チェックをしながら使うと安全です。
$userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
$requestUri = $_SERVER['REQUEST_URI'] ?? '';
$_SERVERの値を信用しすぎない
$_SERVER の中には、サーバー側で設定される情報だけでなく、HTTPリクエストヘッダー由来の値も含まれます。
たとえば、以下のような値です。
$_SERVER['HTTP_USER_AGENT']
$_SERVER['HTTP_REFERER']
$_SERVER['HTTP_HOST']
$_SERVER['HTTP_ACCEPT_LANGUAGE']
これらはクライアント側から送られる情報なので、改ざんされる可能性があります。
そのため、表示用やログ用として使うことはありますが、認証や権限判定など、重要な処理の根拠として使うのは避けた方が安全です。
PHP_SELFを使うときの注意点
$_SERVER['PHP_SELF'] をHTMLにそのまま出力すると、XSSの原因になることがあります。
悪い例です。
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
安全に出力する場合は、htmlspecialchars() でエスケープします。
<form action="<?php echo htmlspecialchars($_SERVER['PHP_SELF'], ENT_QUOTES, 'UTF-8'); ?>" method="post">
ただし、実務では action="" として現在のURLに送信したり、ルーティングで明示的に送信先URLを指定したりすることも多いです。
$_GET
$_GETとは
$_GET は、URLのクエリ文字列から値を取得するためのスーパーグローバル変数です。
たとえば、次のURLにアクセスしたとします。
https://example.com/search.php?keyword=php&page=2
この場合、PHPでは次のように値を取得できます。
echo $_GET['keyword']; // php
echo $_GET['page']; // 2
$_GET は、検索条件、ページ番号、カテゴリ、記事ID、商品IDなどをURLで渡す場合によく使われます。
$_GETはHTTP GETメソッド限定ではない
$_GET という名前から、HTTPメソッドがGETのときだけ値が入ると思われることがあります。
しかし、$_GET はHTTPメソッドそのものではなく、URLのクエリ文字列を扱う変数です。
そのため、POSTリクエストであっても、URLにクエリ文字列が付いていれば $_GET に値が入ります。
たとえば、次のようなリクエストです。
POST /form.php?preview=1
この場合、preview=1 は次のように取得できます。
$preview = $_GET['preview'] ?? '';
$_GETの主な使い道
$_GET は、URLで状態を表したい場合に向いています。
| 用途 | URL例 |
|---|---|
| 検索キーワード | /search.php?keyword=php |
| ページ番号 | /articles.php?page=2 |
| カテゴリ指定 | /products.php?category=shoes |
| 並び替え | /items.php?sort=latest |
| 詳細ページのID | /article.php?id=10 |
検索ページの例です。
$keyword = $_GET['keyword'] ?? '';
echo htmlspecialchars($keyword, ENT_QUOTES, 'UTF-8');
?? は、値が存在しない場合にデフォルト値を指定するために使います。
$keyword = $_GET['keyword'] ?? '';
これは、次のような処理を短く書いたものです。
if (isset($_GET['keyword'])) {
$keyword = $_GET['keyword'];
} else {
$keyword = '';
}
$_GETを使うときの注意点
$_GET の値は、ユーザーがURLを書き換えるだけで簡単に変更できます。
たとえば、次のURLがあるとします。
https://example.com/product.php?id=10
ユーザーは、これを次のように変更できます。
https://example.com/product.php?id=999
そのため、$_GET の値をそのまま信用してはいけません。
悪い例です。
$id = $_GET['id'];
$sql = "SELECT * FROM products WHERE id = $id";
このような書き方は、SQLインジェクションの原因になります。
数値として扱う場合は、まず型を整えます。
$id = (int)($_GET['id'] ?? 0);
さらに、データベースに使う場合はプリペアドステートメントを使います。
$id = (int)($_GET['id'] ?? 0);
$stmt = $pdo->prepare('SELECT * FROM products WHERE id = :id');
$stmt->bindValue(':id', $id, PDO::PARAM_INT);
$stmt->execute();
$_POST
$_POSTとは
$_POST は、主にHTMLフォームからPOST送信されたデータを取得するためのスーパーグローバル変数です。
たとえば、次のようなフォームがあるとします。
<form action="confirm.php" method="post">
<input type="text" name="username">
<input type="email" name="email">
<button type="submit">送信</button>
</form>
PHP側では、次のように取得できます。
$username = $_POST['username'] ?? '';
$email = $_POST['email'] ?? '';
echo htmlspecialchars($username, ENT_QUOTES, 'UTF-8');
echo htmlspecialchars($email, ENT_QUOTES, 'UTF-8');
$_POSTの主な使い道
$_POST は、データを送信・登録・更新する処理でよく使われます。
| 用途 | 例 |
|---|---|
| お問い合わせフォーム | 名前、メールアドレス、本文 |
| ログインフォーム | メールアドレス、パスワード |
| 会員登録フォーム | ユーザー名、メールアドレス、パスワード |
| コメント投稿 | 投稿者名、コメント本文 |
| 商品登録 | 商品名、価格、説明文 |
| プロフィール更新 | 名前、自己紹介文、画像など |
$_GET は検索や絞り込みのようにURLで状態を表したい場合に向いています。
一方、$_POST は登録・更新・送信のように、サーバー側のデータを変更する処理に向いています。
$_POSTはJSONデータを通常そのまま受け取れない
$_POST は、POSTリクエストの本文なら何でも入るわけではありません。
主に、HTMLフォームで送信される以下のような形式のデータを扱います。
application/x-www-form-urlencoded
multipart/form-data
一方、APIなどでよく使われる application/json のデータは、通常 $_POST には入りません。
JSON形式のリクエストボディを受け取る場合は、php://input から読み取ります。
$json = file_get_contents('php://input');
$data = json_decode($json, true);
$name = $data['name'] ?? '';
フォーム処理だけを扱う場合は $_POST で問題ありません。
ただし、API開発では $_POST ではなく、リクエストボディを直接読む必要がある場面もあります。
$_POSTを使うときの注意点
$_POST の値はURLには表示されません。
しかし、URLに表示されないからといって安全なわけではありません。
ユーザーは開発者ツールや外部ツールを使って、任意のPOSTデータを送信できます。
そのため、$_POST の値も必ずチェックする必要があります。
たとえば、お問い合わせフォームでは次のようにバリデーションを行います。
$name = trim($_POST['name'] ?? '');
$email = trim($_POST['email'] ?? '');
$message = trim($_POST['message'] ?? '');
$errors = [];
if ($name === '') {
$errors[] = '名前を入力してください。';
}
if ($email === '' || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = '正しいメールアドレスを入力してください。';
}
if ($message === '') {
$errors[] = '本文を入力してください。';
}
if (empty($errors)) {
echo '送信できます';
}
$_POST を使うときは、以下のような対策が重要です。
| 対策 | 内容 |
|---|---|
| 存在チェック | 値が送信されているか確認する |
| 型チェック | 数値・文字列・配列などを確認する |
| 文字数チェック | 長すぎる入力を防ぐ |
| 形式チェック | メールアドレスなどの形式を確認する |
| エスケープ | HTML出力時にXSSを防ぐ |
| プリペアドステートメント | DB操作時にSQLインジェクションを防ぐ |
| CSRF対策 | 不正なフォーム送信を防ぐ |
$_FILES
$_FILESとは
$_FILES は、フォームからアップロードされたファイル情報を取得するためのスーパーグローバル変数です。
ファイルアップロードを行うフォームでは、enctype="multipart/form-data" を指定する必要があります。
<form action="upload.php" method="post" enctype="multipart/form-data">
<input type="file" name="image">
<button type="submit">アップロード</button>
</form>
PHP側では、次のようにアップロードされたファイル情報を確認できます。
var_dump($_FILES['image']);
$_FILES['image'] には、一般的に次のような情報が入ります。
| キー | 内容 |
|---|---|
name | 元のファイル名 |
type | MIMEタイプ |
tmp_name | 一時保存先 |
error | アップロード時のエラーコード |
size | ファイルサイズ |
$_FILESの基本的な使い方
アップロードされたファイルを保存する場合は、move_uploaded_file() を使います。
if ($_FILES['image']['error'] === UPLOAD_ERR_OK) {
$tmpName = $_FILES['image']['tmp_name'];
$fileName = $_FILES['image']['name'];
move_uploaded_file($tmpName, __DIR__ . '/uploads/' . $fileName);
}
ただし、このコードは実務では安全とはいえません。
ユーザーが送信したファイル名をそのまま保存しているためです。
ファイルアップロード時の注意点
ファイルアップロードは、セキュリティリスクが高い処理です。
特に、以下の値は信用しすぎないようにします。
$_FILES['image']['name']
$_FILES['image']['type']
name は元のファイル名ですが、ユーザー側で自由に変更できます。
type も送信時の情報に依存するため、偽装される可能性があります。
そのため、ファイル形式を確認する場合は、$_FILES['type'] だけで判断せず、finfo などを使って実際のファイル内容を確認します。
if ($_FILES['image']['error'] === UPLOAD_ERR_OK) {
$tmpName = $_FILES['image']['tmp_name'];
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mimeType = $finfo->file($tmpName);
$allowedTypes = [
'image/jpeg' => 'jpg',
'image/png' => 'png',
'image/gif' => 'gif',
];
if (!isset($allowedTypes[$mimeType])) {
exit('許可されていないファイル形式です。');
}
$extension = $allowedTypes[$mimeType];
$newFileName = bin2hex(random_bytes(16)) . '.' . $extension;
$uploadDir = __DIR__ . '/uploads/';
if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0755, true);
}
$destination = $uploadDir . $newFileName;
if (!move_uploaded_file($tmpName, $destination)) {
exit('ファイルの保存に失敗しました。');
}
echo 'アップロードしました。';
}
ファイルアップロードでは、以下のような点を確認しましょう。
| チェック項目 | 内容 |
|---|---|
| エラーコード | UPLOAD_ERR_OK か確認する |
| ファイルサイズ | 上限を超えていないか確認する |
| MIMEタイプ | 許可した形式か確認する |
| 拡張子 | 許可した拡張子にする |
| ファイル名 | ランダムな名前に変更する |
| 保存場所 | 公開ディレクトリ直下を避ける |
| 実行権限 | アップロード先でPHPを実行できないようにする |
| 保存結果 | move_uploaded_file() の戻り値を確認する |
$_COOKIE
$_COOKIEとは
$_COOKIE は、ブラウザから送信されたCookieの値を取得するためのスーパーグローバル変数です。
Cookieをセットするには、setcookie() を使います。
setcookie('theme', 'dark', time() + 3600);
次回以降のリクエストで、次のように取得できます。
$theme = $_COOKIE['theme'] ?? 'light';
Cookieは、ブラウザ側に保存される情報です。
Cookieの主な使い道
Cookieは、ユーザーのブラウザに簡単な情報を保存したい場合に使われます。
| 用途 | 例 |
|---|---|
| 表示設定 | ダークモード、文字サイズ |
| 言語設定 | 日本語、英語など |
| 再訪問判定 | 初回訪問かどうか |
| セッションID | ログイン状態を識別するID |
| 簡易的な状態保持 | カートID、閲覧履歴IDなど |
たとえば、テーマ設定をCookieに保存する場合は、次のように書けます。
setcookie('theme', 'dark', time() + 60 * 60 * 24 * 30);
取得する場合は次のようにします。
$theme = $_COOKIE['theme'] ?? 'light';
if ($theme === 'dark') {
echo 'ダークモードです';
} else {
echo 'ライトモードです';
}
$_COOKIEを使うときの注意点
Cookieはブラウザ側に保存されるため、ユーザーが値を書き換えることができます。
そのため、権限判定のような重要な処理に、Cookieの値をそのまま使ってはいけません。
悪い例です。
if ($_COOKIE['role'] === 'admin') {
echo '管理者ページを表示します';
}
このようなコードでは、Cookieを書き換えられると不正に管理者扱いされる可能性があります。
権限判定を行う場合は、セッションやデータベース上の情報を使います。
session_start();
if (isset($_SESSION['user_id'])) {
// DBからユーザー情報を取得し、権限を確認する
}
また、Cookieにパスワードやクレジットカード番号などの重要情報をそのまま保存してはいけません。
$_SESSION
$_SESSIONとは
$_SESSION は、ユーザーごとのセッション情報を扱うためのスーパーグローバル変数です。
セッションを使うには、最初に session_start() を実行します。
session_start();
$_SESSION['user_id'] = 123;
$_SESSION['username'] = 'Taro';
別のページでも、同じように session_start() を呼び出せば、セッションの値を取得できます。
session_start();
echo $_SESSION['username'] ?? '';
CookieとSessionの違い
Cookieは、ブラウザ側に値を保存します。
一方、Sessionは通常、実際のデータをサーバー側に保存します。
ブラウザ側には、セッションを識別するためのセッションIDがCookieなどで保存されます。
つまり、CookieとSessionの違いを簡単にまとめると以下のようになります。
| 項目 | Cookie | Session |
|---|---|---|
| データの保存場所 | ブラウザ側 | 主にサーバー側 |
| 改ざんリスク | 比較的高い | Cookieより低い |
| 主な用途 | 表示設定、言語設定など | ログイン状態、CSRFトークンなど |
| PHPで使う変数 | $_COOKIE | $_SESSION |
ただし、Sessionでもブラウザ側に保存されるセッションIDが盗まれると危険です。
そのため、ログイン後のセッションID再生成や、HTTPSの利用などが重要になります。
$_SESSIONの主な使い道
$_SESSION は、ログイン状態の管理によく使われます。
session_start();
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
echo 'ログイン中です';
そのほか、以下のような用途があります。
| 用途 | 例 |
|---|---|
| ログイン状態 | user_id |
| CSRFトークン | csrf_token |
| フォーム入力内容の一時保存 | 入力途中の値 |
| カート情報 | 商品ID、数量 |
| フラッシュメッセージ | 「保存しました」などの一度だけ表示するメッセージ |
$_SESSIONを使うときの注意点
$_SESSION を使う場合、session_start() は出力前に呼び出します。
悪い例です。
echo 'Hello';
session_start();
基本的には、PHPファイルの先頭付近で呼び出します。
<?php
session_start();
また、ログイン成功後はセッションIDを再生成するのが安全です。
session_start();
// ログイン成功後
session_regenerate_id(true);
$_SESSION['user_id'] = $user['id'];
これは、セッション固定攻撃を防ぐために重要です。
また、$_SESSION にパスワードやクレジットカード番号などの重要情報を入れるのは避けましょう。
$_REQUEST
$_REQUESTとは
$_REQUEST は、設定に応じて $_GET、$_POST、$_COOKIE 由来の値をまとめて扱うスーパーグローバル変数です。
たとえば、次のように値を取得できます。
$value = $_REQUEST['value'] ?? '';
一見すると、GETでもPOSTでも同じ書き方で取得できるため便利に見えます。
しかし、実務では $_REQUEST の使用は慎重に考える必要があります。
$_REQUESTの内容は設定に依存する
$_REQUEST に何が含まれるかは、PHPの設定に影響されます。
具体的には、request_order や variables_order の設定によって、$_GET、$_POST、$_COOKIE のうち何が含まれるか、同じキーがある場合にどれが優先されるかが変わります。
そのため、$_REQUEST を使うと、値がどこから来たのか分かりにくくなります。
たとえば、次のようなコードがあるとします。
$id = $_REQUEST['id'] ?? '';
この id がURLから来たのか、フォームから来たのか、Cookieから来たのかが、コードを見ただけでは分かりません。
$_REQUESTは多用しない方がよい
実務では、用途に応じて $_GET、$_POST、$_COOKIE を明示的に使い分ける方が安全です。
// URLパラメータを取得する場合
$id = $_GET['id'] ?? null;
// POSTフォームの値を取得する場合
$name = $_POST['name'] ?? '';
// Cookieの値を取得する場合
$token = $_COOKIE['token'] ?? '';
このように書いた方が、値の出どころが明確になります。
$_REQUEST は小さなサンプルコードでは便利に見えますが、セキュリティや保守性を考えると、実務ではなるべく避けた方がよいでしょう。
$_ENV
$_ENVとは
$_ENV は、環境変数を取得するためのスーパーグローバル変数です。
環境変数は、アプリケーションの設定情報をコードの外側で管理するためによく使われます。
たとえば、以下のような情報です。
| 環境変数 | 内容 |
|---|---|
APP_ENV | 本番環境、開発環境など |
DB_HOST | データベースホスト |
DB_NAME | データベース名 |
DB_USER | データベースユーザー |
DB_PASSWORD | データベースパスワード |
API_KEY | 外部APIキー |
PHPでは、次のように取得できます。
$dbHost = $_ENV['DB_HOST'] ?? 'localhost';
$_ENVは環境によって空の場合がある
$_ENV は、PHPの設定や実行環境によって値が入らない場合があります。
たとえば、variables_order の設定に E が含まれていない場合、$_ENV が作られないことがあります。
そのため、環境変数を扱う場合は、getenv() が使われることもあります。
$dbHost = getenv('DB_HOST');
ただし、$_ENV と getenv() の挙動は、実行環境やサーバー設定によって異なる場合があります。
Laravelなどのフレームワークでは、.env ファイルや設定管理機能を使って環境変数を扱うことが一般的です。
スーパーグローバル変数とスコープ
通常の変数は関数内からそのまま使えない
PHPでは、関数の外で定義した通常の変数は、関数の中からそのまま参照できません。
$siteName = 'My Site';
function showSiteName() {
echo $siteName; // そのままでは使えない
}
関数の中で使いたい場合は、global を使う方法があります。
$siteName = 'My Site';
function showSiteName() {
global $siteName;
echo $siteName;
}
または、$GLOBALS を使う方法もあります。
$siteName = 'My Site';
function showSiteName() {
echo $GLOBALS['siteName'];
}
スーパーグローバル変数は関数内からそのまま使える
スーパーグローバル変数は、関数の中でもそのまま使えます。
function getKeyword() {
return $_GET['keyword'] ?? '';
}
global $_GET; のように書く必要はありません。
function showMethod() {
echo $_SERVER['REQUEST_METHOD'];
}
このように、スコープを意識せずに使える点が、スーパーグローバル変数の特徴です。
ただし、どこからでも使えるからといって、どこでも無制限に使うべきではありません。
コードの見通しをよくするためには、必要な値を関数の引数として渡したり、クラスで適切に管理したりすることも大切です。
スーパーグローバル変数の実践例
URLパラメータを取得する
記事IDをURLから取得する例です。
// URL: /article.php?id=10
$id = (int)($_GET['id'] ?? 0);
if ($id <= 0) {
exit('不正なIDです。');
}
echo '記事ID: ' . $id;
$_GET['id'] をそのまま使わず、数値に変換してから利用しています。
POSTフォームを処理する
POST送信された名前を表示する例です。
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = trim($_POST['name'] ?? '');
if ($name === '') {
echo '名前を入力してください。';
} else {
echo htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . 'さん、こんにちは。';
}
}
HTMLに出力する前に htmlspecialchars() を使っている点が重要です。
ログイン状態を確認する
セッションを使ってログイン状態を確認する例です。
session_start();
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
echo 'ログイン中です。';
$_SESSION['user_id'] が存在しない場合は、ログインページへリダイレクトしています。
Cookieを読み取る
Cookieに保存されたテーマ設定を読み取る例です。
$theme = $_COOKIE['theme'] ?? 'light';
if ($theme === 'dark') {
echo 'ダークモードです';
} else {
echo 'ライトモードです';
}
ただし、Cookieはユーザーが変更できるため、重要な判定には使わないようにします。
ファイルをアップロードする
ファイルサイズを確認してアップロードする簡単な例です。
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_FILES['image']) && $_FILES['image']['error'] === UPLOAD_ERR_OK) {
$tmpName = $_FILES['image']['tmp_name'];
$size = $_FILES['image']['size'];
if ($size > 1024 * 1024 * 2) {
exit('ファイルサイズは2MB以下にしてください。');
}
$newName = bin2hex(random_bytes(16)) . '.jpg';
if (!move_uploaded_file($tmpName, __DIR__ . '/uploads/' . $newName)) {
exit('アップロードに失敗しました。');
}
echo 'アップロードしました。';
}
}
実務では、ファイルサイズだけでなく、MIMEタイプや拡張子の確認、保存先の管理も必要です。
スーパーグローバル変数を使うときのセキュリティ対策
外部入力は信用しない
スーパーグローバル変数のうち、以下はユーザーが操作できる値を含みます。
$_GET
$_POST
$_COOKIE
$_FILES
$_REQUEST
また、$_SERVER の中にも、HTTPヘッダー由来の値が含まれます。
そのため、外部から送られてくる値は、基本的に信用しないことが重要です。
たとえば、フォームに入力された名前であっても、ユーザーは次のような文字列を送信できます。
<script>alert('XSS')</script>
このような値をそのままHTMLに出力すると、XSSの原因になります。
HTML出力時はエスケープする
ユーザー入力をHTMLに出力する場合は、htmlspecialchars() を使います。
悪い例です。
echo $_GET['keyword'];
良い例です。
$keyword = $_GET['keyword'] ?? '';
echo htmlspecialchars($keyword, ENT_QUOTES, 'UTF-8');
改行を含むコメントを表示したい場合は、次のように書くこともあります。
$comment = $_POST['comment'] ?? '';
echo nl2br(htmlspecialchars($comment, ENT_QUOTES, 'UTF-8'));
SQLに直接埋め込まない
ユーザー入力をSQLに直接埋め込むと、SQLインジェクションの危険があります。
悪い例です。
$email = $_POST['email'];
$sql = "SELECT * FROM users WHERE email = '$email'";
良い例です。
$email = $_POST['email'] ?? '';
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email');
$stmt->bindValue(':email', $email, PDO::PARAM_STR);
$stmt->execute();
データベースを扱う場合は、プリペアドステートメントを使うのが基本です。
数値は数値として扱う
URLからページ番号やIDを取得する場合は、数値として扱うことが多いです。
悪い例です。
$page = $_GET['page'];
良い例です。
$page = (int)($_GET['page'] ?? 1);
if ($page < 1) {
$page = 1;
}
数値として使う値は、必ず型を整えてから処理しましょう。
存在チェックを行う
存在しないキーを直接参照すると、警告の原因になります。
悪い例です。
echo $_GET['keyword'];
良い例です。
echo $_GET['keyword'] ?? '';
または、isset() を使います。
if (isset($_GET['keyword'])) {
echo $_GET['keyword'];
}
現在のPHPでは、?? を使うと簡潔に書けます。
CSRF対策を行う
POSTフォームでは、CSRF対策も重要です。
CSRFとは、ユーザーが意図しないリクエストを送信させられる攻撃です。
対策として、セッションにトークンを保存し、フォーム送信時に照合します。
session_start();
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
フォーム側では、hiddenフィールドにトークンを埋め込みます。
<input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($_SESSION['csrf_token'], ENT_QUOTES, 'UTF-8'); ?>">
送信後に照合します。
session_start();
$token = $_POST['csrf_token'] ?? '';
if (!hash_equals($_SESSION['csrf_token'] ?? '', $token)) {
exit('不正なリクエストです。');
}
フォーム処理では、入力チェックだけでなく、CSRF対策も意識しましょう。
$_GETと$_POSTの違い
$_GETの特徴
$_GET は、URLのクエリ文字列から値を取得します。
/search.php?keyword=php&page=2
特徴は以下です。
| 項目 | 内容 |
|---|---|
| URLに表示される | はい |
| ブックマークしやすい | はい |
| 共有しやすい | はい |
| 検索・絞り込みに向いている | はい |
| 大量データの送信に向いている | いいえ |
| パスワード送信に向いている | いいえ |
$_GET は、検索条件やページ番号のように、URLとして共有したい情報に向いています。
$_POSTの特徴
$_POST は、主にフォームからPOST送信された値を取得します。
特徴は以下です。
| 項目 | 内容 |
|---|---|
| URLに表示される | いいえ |
| 登録・更新処理に向いている | はい |
| ログインフォームに使われる | はい |
| GETより大きめのデータを送信しやすい | はい |
| 安全性 | URLに出ないだけで安全とは限らない |
$_POST は、お問い合わせ送信、ログイン、会員登録、コメント投稿、プロフィール更新などに向いています。
$_GETと$_POSTの使い分け
基本的には、以下のように使い分けます。
| やりたいこと | 使う変数 |
|---|---|
| 検索条件を渡したい | $_GET |
| ページ番号を渡したい | $_GET |
| 記事IDや商品IDをURLで渡したい | $_GET |
| お問い合わせフォームを送信したい | $_POST |
| ログイン情報を送信したい | $_POST |
| データを登録・更新したい | $_POST |
ただし、$_POST はURLに表示されないだけで、安全という意味ではありません。
どちらを使う場合でも、入力チェックやエスケープは必須です。
スーパーグローバル変数のよくあるミス
存在しないキーを直接参照する
悪い例です。
echo $_GET['keyword'];
keyword が存在しない場合、警告が出ることがあります。
良い例です。
echo $_GET['keyword'] ?? '';
入力値をそのままHTMLに出力する
悪い例です。
echo $_POST['comment'];
良い例です。
$comment = $_POST['comment'] ?? '';
echo nl2br(htmlspecialchars($comment, ENT_QUOTES, 'UTF-8'));
入力値をSQLに直接入れる
悪い例です。
$id = $_GET['id'];
$sql = "SELECT * FROM articles WHERE id = $id";
良い例です。
$id = (int)($_GET['id'] ?? 0);
$stmt = $pdo->prepare('SELECT * FROM articles WHERE id = :id');
$stmt->bindValue(':id', $id, PDO::PARAM_INT);
$stmt->execute();
Cookieの値で権限判定する
悪い例です。
if ($_COOKIE['role'] === 'admin') {
echo '管理者ページ';
}
良い例です。
session_start();
if (isset($_SESSION['user_id'])) {
// DBからユーザー権限を確認する
}
Cookieはユーザーが変更できるため、権限判定には向きません。
$_REQUESTを何でも使う
悪い例です。
$value = $_REQUEST['value'] ?? '';
良い例です。
// 検索条件ならGET
$keyword = $_GET['keyword'] ?? '';
// フォーム投稿ならPOST
$message = $_POST['message'] ?? '';
// CookieならCOOKIE
$token = $_COOKIE['token'] ?? '';
値の出どころを明確にするために、$_GET、$_POST、$_COOKIE を使い分けましょう。
スーパーグローバル変数の使い分け早見表
目的別の使い分け
| やりたいこと | 使うスーパーグローバル変数 |
|---|---|
URLの ?id=10 を取得したい | $_GET |
| 検索キーワードを取得したい | $_GET |
| ページ番号を取得したい | $_GET |
| フォーム送信内容を取得したい | $_POST |
| JSONリクエストを受け取りたい | php://input |
| ファイルアップロードを処理したい | $_FILES |
| Cookieの値を読みたい | $_COOKIE |
| ログイン状態を管理したい | $_SESSION |
| CSRFトークンを保存したい | $_SESSION |
| リクエストメソッドを判定したい | $_SERVER |
| アクセス元IPを見たい | $_SERVER |
| 環境変数を読みたい | $_ENV または getenv() |
| グローバル変数を関数内から参照したい | $GLOBALS |
| GET・POST・COOKIEをまとめて扱いたい | $_REQUEST、ただし多用は非推奨 |
初心者がまず覚えるべき変数
初心者のうちは、まず以下の4つを優先して覚えるとよいです。
| 変数 | 役割 |
|---|---|
$_GET | URLパラメータを取得する |
$_POST | フォーム送信内容を取得する |
$_SESSION | ログイン状態などを管理する |
$_SERVER | リクエスト情報やサーバー情報を取得する |
ファイルアップロードを扱う場合は $_FILES、Cookieを扱う場合は $_COOKIE、環境変数を扱う場合は $_ENV も覚えていきましょう。
まとめ
PHPのスーパーグローバル変数は、PHPがあらかじめ用意している特別な変数です。
関数やメソッドの中でも global 宣言なしで使えるため、フォーム処理、ログイン管理、URLパラメータ取得、ファイルアップロードなど、Webアプリケーション開発でよく使われます。
代表的なスーパーグローバル変数は以下です。
$GLOBALS // グローバル変数を参照する
$_SERVER // サーバー情報・リクエスト情報
$_GET // URLのクエリ文字列
$_POST // POST送信されたフォームデータ
$_FILES // アップロードファイル情報
$_COOKIE // Cookieの値
$_SESSION // セッション情報
$_REQUEST // GET・POST・COOKIE由来の値
$_ENV // 環境変数
ただし、スーパーグローバル変数の多くは外部入力を扱います。
特に、以下の値はユーザーが変更できる可能性があります。
$_GET
$_POST
$_COOKIE
$_FILES
$_REQUEST
また、$_SERVER の中にもHTTPヘッダー由来の値が含まれるため、信用しすぎないことが大切です。
スーパーグローバル変数を安全に使うためには、以下を意識しましょう。
| 対策 | 内容 |
|---|---|
| 存在チェック | ?? や isset() を使う |
| 型変換 | 数値は (int) などで型を整える |
| バリデーション | 入力内容が正しい形式か確認する |
| エスケープ | HTML出力時は htmlspecialchars() を使う |
| SQL対策 | プリペアドステートメントを使う |
| CSRF対策 | トークンを使って不正送信を防ぐ |
| ファイル検証 | MIMEタイプ・サイズ・保存名を確認する |
スーパーグローバル変数は非常に便利ですが、「どこからでも使える変数」ではなく、「外部入力を扱うことが多い変数」として慎重に扱うことが重要です。
特に実務では、$_REQUEST に頼りすぎず、$_GET、$_POST、$_COOKIE を明示的に使い分けることで、読みやすく安全なコードを書きやすくなります。
以上、PHPのスーパーグローバル変数についてでした。
最後までお読みいただき、ありがとうございました。










