PHP入門 リクエスト情報 ヘッダー情報($_SERVER)
クライアントからサーバーに送信される情報は、クライアントの種類や対応する言語、リンク元のページなど、さまざまな情報が内部的に生成されて、サーバーに送信されています。このような不可視の情報のことをヘッダー情報(リクエストヘッダー情報)と言います。
ヘッダー情報の種類
chromeブラウザのデベロッパーツールで見たヘッダー情報
HTTP通信で利用可能な主なヘッダー
種類 | ヘッダー名 | 概要 |
---|---|---|
一般 | Cache-Control | キャッシュルールを規定する |
Connection | レスポンス後に接続を維持するか | |
Date | コンテンツを生成した日時 | |
Transfer-Encoding | コンテンツの転送エンコーディング方式 | |
リクエスト | Accept | クライアントがサポートしているコンテンツの種類(優先順) |
Accept-Language | クライアントが対応している言語(優先順) | |
Authorization | 認証情報 | |
Cookie | クライアントに保存されたクッキーを送信 | |
Host | 要求先のホスト名 | |
If-Modified-Since | 指定された日時以降にコンテンツが更新されている場合にのみ、サーバーはデータを送信 | |
Proxy-Authorization | プロキシサーバー用の認証情報 | |
Range | 要求するリソースの範囲 | |
Referer | リンク元のURl | |
User-Agent | クライアントの種類 | |
レスポンス | ETag | リソースを一意に特定するためのキー情報(コンテンツが更新されていないかどうかを特定する場合などに使用) |
Expires | コンテンツの有効期限 | |
Last-Modified | コンテンツの最終更新年月日 | |
Location | クライアントに新しいURIに移動するように促す | |
Server | サーバーの種類 | |
Set-Cookie | クライアントにクッキーを送信 | |
WWW-Authenticate | クライアントに認証を要求 | |
エンティティ | Content-Encoding | コンテンツのエンコーディング方式 |
Content-Length | コンテンツのサイズ | |
Content-Type | コンテンツの種類 |
ヘッダー情報の利用方法
ヘッダーには多数の情報が含まれています。これらの情報をさまざまな目的に利用できます。たとえば、User-Agentヘッダーを利用すれば、サイトにアクセスしてきたクライアントの種類がわかります。これをアクセスログとして記憶しておけば、自分のページにアクセスしているユーザーの傾向を把握したり、検索エンジンのクローラーの巡回頻度を知ることができます。あるいは、デスクトップブラウザか携帯端末向けのブラウザを区別してコンテンツ形式を選択的に出力する、などといったことも可能です。Refererヘッダーを利用することで、自分のサイトにどのようなページからリンクが張られているのか、自分のサイト内でユーザーがどのようにページ間を移動しているのか把握できます。アクセス数だけではなく、このような傾向もあわせて分析することで、コンテンツそのおのやサイトの構造を改善する手がかりになります。
また、Accept-Languageヘッダーはクライアントの対応言語を表します。この情報をもとにすれば日本語環境のユーザーには日本語、英語環境のユーザーには英語を表示するというように、クライアントの言語に応じたページを構築することもできます。
リクエストヘッダーを取得する
リクエストヘッダーを取得するには、スーパーグローバル変数$_SERVERを参照します。ただし、$_SERVERはリクエストヘッダーの他に、サーバー変数(サーバーが提供する環境情報)を含みます。$_SERVERでは、ヘッダー情報とサーバー変数とを識別するために、生のヘッダー名を次の規則で整形したものを格納しています。
- ハイフン(-)はアンダースコア(_)に変換
- 接頭辞として「HTTP_」を付加
したがって、User-Agentヘッダーを取得するには、$_SERVER[‘HTTP_USER_AGENT’]のように記述する必要があります。(ヘッダー名はすべて大文字で記述します)str_starts_with関数で「HTTP_」で始まるキー名だけを取り出すことで、リクエストヘッダーの情報だけを出力しています。
主なサーバー変数
変数名 | 概要 | 値(例) |
---|---|---|
DOCUMENT_ROOT | ドキュメントルート | C:/xampp/htdocs |
GATEWAY_INTERFACE | CGIのリビジョン | CGI/1.1 |
HTTPS | HTTPSプロトコルを利用しているか | – |
PATH_INFO | 実行ファイル名とクエリ文字列の間のパス情報 | /tmp |
PATH_TRANSLATED | 実行中のスクリプトのファイルシステム上のパス | C:\xampp\htdocs\tmp |
PHP_SELF | 実行中のスクリプト | /tmp |
PHP_AUTH_DIGEST | HTTPダイジェスト認証時のAuthorizationヘッダーの内容 | – |
PHP_AUTH_USER | HTTP認証時のユーザー名 | admin_usr |
PHP_AUTH_PW | HTTP認証時のパスワード | admin_pass |
QUERY_STRING | クエリ情報 | category=PHP |
REMOTE_ADDR | クライアントのIPアドレス | ::1 |
REMOTE_HOST | クライアントのホスト名 | localhost |
REMOTE_PORT | クライアントのポート番号 | 49877 |
REQUEST_METHOD | HTTPメソッド | GET |
REQUEST_TIME | リクエスト開始時のタイムスタンプ | 1609140540 |
REQUEST_URI | 指定されたURI | C:/xampp/htdocs |
SCRIPT_FILENAME | 実行中のスクリプト(絶対パス) | C:/xampp/htdocs/sample.php |
SCRIPT_NAME | 実行中のスクリプト | /htdocs/sample.php |
SERVER_ADDR | サーバーのIPアドレス | ::1 |
SERVER_ADMIN | サーバー管理者のメールアドレス | webmaster@example.com |
SERVER_NAME | サーバー名 | localhost |
SERVER_PORT | サーバーのポート | 80 |
SERVER_PROTOCOL | プロトコル名、リビジョン | HTTP/1.1 |
SERVER_SIGNATURE | サーバーのバージョン | <address>Apache/2.4.46</address> |
SERVER_SOFTWARE | サーバーのソフトウェア | Apache/2.4.46 |
<?php require_once './Encode.php';?>
<!DOCTYPE html>
<head>
<meta charset="UTF-8" />
<title>PHPサンプル</title>
<style>
th,td{
border:solid 1px;
text-align: left;
}
</style>
</head>
<body>
<table>
<?php
//$_SERVERのキー/値を順に取得
foreach($_SERVER as $key => $value){
//キー($key)が「HTTP_」ではじまる場合のみ、その値を出力
if(str_starts_with($key, 'HTTP_')){
?>
<tr>
<th><?=e($key)?></th>
<th><?=e($value)?></th>
<?php
}
}
?>
</table>
</body>
</html>
レスポンスヘッダーを設定する
PHPからスクリプトからレスポンスヘッダーを操作することも可能です。
Locationヘッダーでリダイレクトする
例:Locationヘッダーを設定することで、指定したページにリダイレクトする
<?php
header('Location: http://localhost/sample2.php');
構文:header関数
header(string $header [, bool $replace = true [, int $response_code]]): void
$header | ヘッダー文字列(「ヘッダー名:値」の形式) |
$replace | 同名のヘッダーが出力済みである場合に置き換えるか |
$response_code | HTTP応答ステータス |
レスポンスヘッダーを設定するのは、header関数の役割です。また、Locationヘッダーは、リダイレクト先のURI(URL)を表すためのレスポンスヘッダーです。クライアントのブラウザではLocationヘッダーを受け取ると、指定のアドレスへ自動的にリクエストを発行します。リダイレクトは1つのリクエスト処理に見えますが、HTTPの観点では、2回のリクエストが自動的に行われています。
リダイレクト先を表すホスト名やフォルダのパスは、実際にはスーパーグローバル変数$_SERVERを使って取得する方法
redirect.php
header('Location: http://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/req_headers.php');
$_SERVER[‘HTTP_HOST’]はサーバーのホスト名、$_SERVER[’PHP_SELF’]は実行中のスクリプトのパスを表します。dirnameはパスから親フォルダのパスを取り出すための関数です。
キャッシュ処理を無効にする
Expires、Last-Modified、Cache-Controlなどのレスポンスヘッダーを指定することで、ブラウザやプロキシサーバーでのキャッシュ処理を強制的に無効にできます。
<?php
//ページの有効期限を過去の日付に設定
header('Expires: Sun, 15 Jan 1970 00:00:00 GMT');
//最終更新日を常に最新
header('Last-Modified: '. gmdate('D, d M Y H:i:s').'GMT');
//キャッシュを無効に設定
header('Cache-Control: no-store, no-cache, must-revalidate');
強制的に認証ダイアログを表示させる
HTTPステータスとして「401 Unauthorized」(未認証)を発行することで、ブラウザで強制的に認証ダイアログを表示できます。➊は強制的に認証ダイアログを表示させるコード。キャンセルされた場合は❷以降の処理を実行し、ユーザー名/パスワードが入力された場合は、再度、phpが読み込まれます。
<?php
//認証ユーザー名が送信されているか判定
if(!isset($_SERVER['PHP_AUTH_USER'])){
header('HTTP/1.1 401 Unauthorized'); //➊
header('WWW-Authenticate: Basic realm="SelfPHP"'); //➊
print 'この画面へのアクセスは認められませんでした。'; //➋
die();
//認証ユーザー名が送信されている場合はユーザー名/パスワードを確認
}else{
//認証ユーザー名が送信されている場合はユーザー名/パスワードを確認
if($_SERVER['PHP_AUTH_USER'] === 'admin_usr' && $_SERVER['PHP_AUTH_PW'] === 'admin_pass'){
print '正しく認証が行われました。';
}else{
print 'ユーザー名、またはパスワードが間違っています。';
}
}
さまざまな種類のファイルを生成したい
クライアントは受信したコンテンツをどのように処理するかは、Content-Typeヘッダー(コンテンツタイプ)によって決定します。PHPは既定で「text/html」というコンテンツタイプを送信します。HTML以外のデータを送信する場合は、スクリプト側で明示的にContent-Typeヘッダーを生成する必要があります。
header('Content-Type: application/pdf'); //PDF文書を出力
主なコンテンツタイプ
コンテンツタイプ | ファイルの種類 | 拡張子 |
---|---|---|
application/octet-stream | 任意のバイナリデータ | – |
application/pdf | PDF文書 | |
image/gif | GIF画像 | .gif |
image/jpeg | JPEG画像 | .jpeg、.jpg |
image/png | PNG画像 | .png |
text/css | CSSスタイルシート | .css |
text/html | HTML文書 | .htm、.html |
text/plain | 普通のテキスト | .txt |
text/xml | XML文書 | .xml |
application/json | JSONデータ | .json |
audio/mpeg | 音声データ | .mp3 |
Content-Typeヘッダーを利用することで、ファイルを強制的にダウンロードさせるようなスクリプトも記述できます。
<?php
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename = "flower.jpg"');
print file_get_contents('./doc/flower.jpg');