タイトル: $_SERVER
SEOタイトル: PHP $_SERVER スーパーグローバル変数(DOCUMENT_ROOT / PHP_SELF / REQUEST_URI / HTTP_USER_AGENT / 一覧)
この本文には実行可能なタグ等が含まれるため、安全のためHTMLソースとして表示しています。本文データは変更していません。
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;background:#fffbea;border:1px solid #f4c430;margin:1em 0;width:100%"><tr><td style="background:#f4c430;color:#000;font-weight:bold;padding:8px">この記事の要点</td></tr><tr><td style="padding:10px"><ul><li><strong>$_SERVER</strong> は<strong>サーバ情報・実行環境・クライアントから送信されたヘッダ</strong>を格納する PHP スーパーグローバル変数</li><li><code>$_SERVER["DOCUMENT_ROOT"]</code> や <code>$_SERVER["PHP_SELF"]</code> のように<strong>要素キー</strong>で値を取り出す</li><li><strong>クライアント由来の値</strong>(<code>HTTP_*</code> / <code>REQUEST_URI</code> / <code>QUERY_STRING</code> 等)は<strong>偽装可能</strong>のため、無加工で出力すると XSS / ヘッダインジェクションになる</li><li>PHP-CLI と PHP-FPM / mod_php で<strong>使えるキーが異なる</strong>。<code>HTTP_HOST</code> や <code>REQUEST_URI</code> は Web サーバ経由のみ</li><li>配列は <code>print_r($_SERVER)</code> / <code>var_dump($_SERVER)</code> で<strong>全キー</strong>を確認できる</li></ul></td></tr></table>
<h2>$_SERVER とは</h2>
<p><strong>$_SERVER</strong> は PHP の<strong>スーパーグローバル変数</strong>(どこからでもアクセスできる組み込み配列)の 1 つで、<strong>Web サーバや実行環境、クライアントから送信された情報</strong>がキー付きで格納されています。Web アプリケーションでリクエスト元の URL、IP、ユーザーエージェント、リファラなどを取得するときに使います。</p>
<h2>基本構文</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">echo $_SERVER['DOCUMENT_ROOT']; // /var/www/html
echo $_SERVER['PHP_SELF']; // /index.php
echo $_SERVER['REQUEST_URI']; // /index.php?id=10
echo $_SERVER['HTTP_USER_AGENT']; // Mozilla/5.0 ...
echo $_SERVER['REMOTE_ADDR']; // 接続元 IP</code></pre>
<h2>主要な要素一覧</h2>
<h3>パス / 実行ファイル系</h3>
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>キー</th><th>意味</th><th>例</th></tr></thead>
<tbody>
<tr><td><code>DOCUMENT_ROOT</code></td><td>ドキュメントルートのフルパス</td><td><code>/var/www/html</code></td></tr>
<tr><td><code>SCRIPT_FILENAME</code></td><td>実行中スクリプトの絶対パス</td><td><code>/var/www/html/index.php</code></td></tr>
<tr><td><code>SCRIPT_NAME</code></td><td>実行中スクリプトのドキュメントルートからの相対パス</td><td><code>/index.php</code></td></tr>
<tr><td><code>PHP_SELF</code></td><td>同上(path_info を含む)</td><td><code>/index.php/foo</code></td></tr>
</tbody>
</table>
<h3>リクエスト URL 系</h3>
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>キー</th><th>意味</th><th>例</th></tr></thead>
<tbody>
<tr><td><code>REQUEST_URI</code></td><td>クエリを含むリクエストパス</td><td><code>/article?id=10</code></td></tr>
<tr><td><code>QUERY_STRING</code></td><td>?以降のクエリ文字列</td><td><code>id=10&page=2</code></td></tr>
<tr><td><code>REQUEST_METHOD</code></td><td>HTTP メソッド</td><td><code>GET</code> / <code>POST</code></td></tr>
<tr><td><code>HTTPS</code></td><td>HTTPS なら <code>on</code></td><td><code>on</code> / 未設定</td></tr>
<tr><td><code>SERVER_PROTOCOL</code></td><td>HTTP バージョン</td><td><code>HTTP/1.1</code></td></tr>
</tbody>
</table>
<h3>クライアント / 接続元系</h3>
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>キー</th><th>意味</th><th>例</th></tr></thead>
<tbody>
<tr><td><code>REMOTE_ADDR</code></td><td>接続元 IP</td><td><code>203.0.113.10</code></td></tr>
<tr><td><code>REMOTE_PORT</code></td><td>接続元ポート</td><td><code>54321</code></td></tr>
<tr><td><code>HTTP_USER_AGENT</code></td><td>ブラウザの UA 文字列</td><td><code>Mozilla/5.0 ...</code></td></tr>
<tr><td><code>HTTP_REFERER</code></td><td>遷移元 URL</td><td><code>https://google.com/</code></td></tr>
<tr><td><code>HTTP_ACCEPT_LANGUAGE</code></td><td>言語設定</td><td><code>ja,en;q=0.8</code></td></tr>
<tr><td><code>HTTP_HOST</code></td><td>リクエスト先ホスト</td><td><code>example.com</code></td></tr>
<tr><td><code>HTTP_X_FORWARDED_FOR</code></td><td>プロキシ経由の元 IP</td><td><code>203.0.113.10</code></td></tr>
</tbody>
</table>
<h3>サーバ系</h3>
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>キー</th><th>意味</th><th>例</th></tr></thead>
<tbody>
<tr><td><code>SERVER_NAME</code></td><td>サーバ名(VirtualHost 名)</td><td><code>example.com</code></td></tr>
<tr><td><code>SERVER_ADDR</code></td><td>サーバ IP</td><td><code>10.0.0.5</code></td></tr>
<tr><td><code>SERVER_PORT</code></td><td>サーバポート</td><td><code>443</code></td></tr>
<tr><td><code>SERVER_SOFTWARE</code></td><td>Web サーバの種類</td><td><code>nginx/1.25.0</code></td></tr>
<tr><td><code>REQUEST_TIME</code></td><td>リクエスト受付時刻(UNIX 時刻)</td><td><code>1718000000</code></td></tr>
<tr><td><code>REQUEST_TIME_FLOAT</code></td><td>同(マイクロ秒精度)</td><td><code>1718000000.123</code></td></tr>
</tbody>
</table>
<h2>現在の完全な URL を組み立てる</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">function currentUrl(): string {
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
? 'https' : 'http';
$host = $_SERVER['HTTP_HOST'] ?? 'localhost';
$uri = $_SERVER['REQUEST_URI'] ?? '/';
return $scheme . '://' . $host . $uri;
}
echo currentUrl();
// https://example.com/article?id=10</code></pre>
<h2>クライアント IP を安全に取る</h2>
<p>ロードバランサや CDN(Cloudflare 等)の背後では <code>REMOTE_ADDR</code> はプロキシの IP になります。元のクライアント IP は <code>HTTP_X_FORWARDED_FOR</code> から取得しますが、<strong>信頼できるプロキシ経由かを検証</strong>しないと偽装されます。</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">function clientIp(): string {
// 信頼できる前段プロキシ(CDN / LB)の IP リスト
$trusted = ['10.0.0.1', '10.0.0.2'];
$remote = $_SERVER['REMOTE_ADDR'] ?? '';
if (in_array($remote, $trusted, true)
&& !empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
// 左端が元クライアント
$forwarded = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
return trim($forwarded[0]);
}
return $remote;
}</code></pre>
<h2>安全に出力する</h2>
<p><strong>$_SERVER のクライアント由来の値(HTTP_*, REQUEST_URI, PHP_SELF など)は偽装可能</strong>です。HTML や属性に埋め込むときは必ずエスケープします。</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">// NG: そのまま出力すると XSS
echo $_SERVER['HTTP_USER_AGENT'];
// OK: htmlspecialchars でエスケープ
echo htmlspecialchars(
$_SERVER['HTTP_USER_AGENT'] ?? '',
ENT_QUOTES | ENT_HTML5,
'UTF-8'
);
// フォームの action に PHP_SELF を埋め込むのは特に危険
// <form action="<?= $_SERVER['PHP_SELF'] ?>"> は XSS の温床
// ハードコードか htmlspecialchars 必須</code></pre>
<h2>全キーを確認する</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">// 全キー値を出力(デバッグ用、本番では出さない)
echo '<pre>';
print_r($_SERVER);
echo '</pre>';
// または var_dump
var_dump($_SERVER);</code></pre>
<h2>CLI 実行時の違い</h2>
<p>PHP を <code>php script.php</code> のように<strong>コマンドラインから実行</strong>すると、<code>HTTP_*</code> や <code>REQUEST_URI</code> など Web リクエスト由来の要素は<strong>存在しません</strong>。代わりに <code>argv</code> / <code>argc</code> が使えます。</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">// CLI のみ
echo $_SERVER['argv'][0]; // スクリプトファイル名
echo $_SERVER['argc']; // 引数の個数
print_r($_SERVER['argv']); // 全引数
// 環境分岐
if (php_sapi_name() === 'cli') {
echo "CLI mode\n";
} else {
echo "Web mode\n";
}</code></pre>
<h2>$_SERVER と関連スーパーグローバル</h2>
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>変数</th><th>用途</th></tr></thead>
<tbody>
<tr><td><code>$_SERVER</code></td><td>サーバ / 環境 / リクエスト情報</td></tr>
<tr><td><code>$_GET</code></td><td>クエリ文字列の値</td></tr>
<tr><td><code>$_POST</code></td><td>POST ボディの値</td></tr>
<tr><td><code>$_COOKIE</code></td><td>Cookie の値</td></tr>
<tr><td><code>$_SESSION</code></td><td>セッション変数</td></tr>
<tr><td><code>$_FILES</code></td><td>アップロードファイル</td></tr>
<tr><td><code>$_REQUEST</code></td><td>$_GET + $_POST + $_COOKIE のマージ</td></tr>
<tr><td><code>$_ENV</code></td><td>環境変数</td></tr>
</tbody>
</table>
<h2>FAQ</h2>
<p><strong>Q: HTTP_HOST と SERVER_NAME どちらを使うべき?</strong><br />
A: <code>HTTP_HOST</code> はクライアントが送ったヘッダ(偽装可)、<code>SERVER_NAME</code> はサーバ設定(VirtualHost)由来。多くの場合 <code>HTTP_HOST</code> が便利ですが、絶対 URL を組む際は<strong>許可ホストのホワイトリスト検証</strong>を入れます。</p>
<p><strong>Q: REQUEST_TIME と time() の違いは?</strong><br />
A: <code>$_SERVER['REQUEST_TIME']</code> はリクエスト受付時刻で固定。<code>time()</code> は呼び出し時の現在時刻。リクエスト全体で同じ「現在時刻」を扱いたいなら REQUEST_TIME。</p>
<h2>関連</h2>
<ul>
<li>スーパーグローバル変数 — PHP の組み込み配列</li>
<li>$_GET / $_POST — リクエストパラメータ</li>
<li>htmlspecialchars — XSS 対策のエスケープ</li>
<li>filter_input — INPUT_SERVER 等で安全に取得</li>
</ul>