PHPでWebアプリケーションを開発していると、ページのリダイレクトやファイルのダウンロード、キャッシュ制御など、様々な場面でHTTPヘッダーを操作する必要があります。そんな時に活躍するのがheader関数です。
今回は、PHPのheader関数について、基本的な使い方から実践的な活用例まで、初心者にも分かりやすく詳しく解説していきます。
header関数とは?
header関数は、PHPからHTTPヘッダーを送信するための組み込み関数です。Webサーバーからブラウザやクライアントアプリケーションに対して、様々な情報や指示を伝えることができます。
基本構文
header(string $header, bool $replace = true, int $response_code = 0)
- $header: 送信するヘッダー文字列
- $replace: 同じヘッダーを置き換えるかどうか(デフォルト: true)
- $response_code: HTTPレスポンスコードを設定
header関数の重要なルール
header関数を使用する際には、以下の重要なルールを理解しておく必要があります。
1. HTMLの出力前に実行する
最も重要なルールは、header関数はHTMLやテキストの出力前に実行しなければならないということです。
<?php
// ❌ 間違った例
echo "Hello World";
header("Location: https://example.com"); // エラーが発生
?>
<?php
// ✅ 正しい例
header("Location: https://example.com");
echo "Hello World";
?>
2. 空白文字にも注意
PHPの開始タグ前に空白があるだけでもエラーになります。
<?php // ❌ 開始タグ前に空白がある
header("Location: https://example.com");
?>
<?php // ✅ 正しい書き方
header("Location: https://example.com");
?>
実践的な使用例
1. ページリダイレクト
最も頻繁に使用される機能の一つです。
<?php
// 別のページにリダイレクト
header("Location: https://example.com/success.php");
exit(); // リダイレクト後の処理を停止
?>
重要: リダイレクト後は必ずexit()
またはdie()
を呼び出して、後続の処理を停止しましょう。
2. HTTPステータスコードの設定
<?php
// 404 Not Found
header("HTTP/1.1 404 Not Found");
// または
http_response_code(404);
header("Content-Type: text/html; charset=UTF-8");
?>
3. コンテンツタイプの指定
<?php
// JSON形式のデータを返す
header("Content-Type: application/json; charset=UTF-8");
echo json_encode(["message" => "Hello World"]);
?>
<?php
// CSVファイルとしてダウンロード
header("Content-Type: text/csv");
header("Content-Disposition: attachment; filename=\"data.csv\"");
echo "名前,年齢,職業\n";
echo "田中太郎,30,エンジニア\n";
?>
4. キャッシュ制御
<?php
// キャッシュを無効にする
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
header("Pragma: no-cache");
?>
<?php
// 1時間キャッシュする
header("Cache-Control: public, max-age=3600");
header("Expires: " . gmdate("D, d M Y H:i:s", time() + 3600) . " GMT");
?>
5. ファイルダウンロード
<?php
$filename = "sample.pdf";
$filepath = "/path/to/file/" . $filename;
if (file_exists($filepath)) {
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"" . $filename . "\"");
header("Content-Length: " . filesize($filepath));
readfile($filepath);
exit();
} else {
header("HTTP/1.1 404 Not Found");
echo "ファイルが見つかりません";
}
?>
6. CORS(Cross-Origin Resource Sharing)の設定
<?php
// 特定のドメインからのアクセスを許可
header("Access-Control-Allow-Origin: https://example.com");
// すべてのドメインからのアクセスを許可(開発環境のみ推奨)
header("Access-Control-Allow-Origin: *");
// 許可するHTTPメソッド
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE");
// 許可するヘッダー
header("Access-Control-Allow-Headers: Content-Type, Authorization");
?>
よくあるエラーとその対処法
1. “Headers already sent” エラー
<?php
echo "何かの出力"; // この行が原因
header("Location: redirect.php"); // エラー発生
?>
対処法:
- header関数を出力より前に移動する
- 出力バッファリング(ob_start())を使用する
<?php
ob_start(); // 出力バッファリング開始
echo "何かの出力";
header("Location: redirect.php");
ob_end_clean(); // バッファをクリア
?>
2. 文字エンコーディングの問題
<?php
// 日本語を含むヘッダーを送信する場合
header("Content-Disposition: attachment; filename=\"" . urlencode("日本語ファイル名.txt") . "\"");
?>
セキュリティ上の注意点
1. オープンリダイレクト脆弱性
<?php
// ❌ 危険な例
$redirect_url = $_GET['url'];
header("Location: " . $redirect_url);
?>
<?php
// ✅ 安全な例
$redirect_url = $_GET['url'];
$allowed_urls = [
'https://example.com/page1.php',
'https://example.com/page2.php'
];
if (in_array($redirect_url, $allowed_urls)) {
header("Location: " . $redirect_url);
} else {
header("Location: /error.php");
}
?>
2. HTTPヘッダーインジェクション
<?php
// ❌ 危険な例
$user_input = $_GET['type'];
header("Content-Type: " . $user_input);
?>
<?php
// ✅ 安全な例
$user_input = $_GET['type'];
$allowed_types = ['text/html', 'application/json', 'text/plain'];
if (in_array($user_input, $allowed_types)) {
header("Content-Type: " . $user_input);
} else {
header("Content-Type: text/html");
}
?>
headers_list関数との組み合わせ
header関数と合わせて覚えておきたいのがheaders_list()
関数です。この関数を使うことで、現在設定されているヘッダーの一覧を取得できます。
headers_list関数の基本的な使い方
<?php
// ヘッダーを設定
header("Content-Type: application/json");
header("Cache-Control: no-cache");
header("X-Custom-Header: MyValue");
// 設定されたヘッダーの一覧を取得
$headers = headers_list();
print_r($headers);
/*
出力例:
Array
(
[0] => Content-Type: application/json
[1] => Cache-Control: no-cache
[2] => X-Custom-Header: MyValue
)
*/
?>
デバッグ時の活用例
<?php
function debug_headers() {
echo "<h3>現在設定されているヘッダー:</h3>";
echo "<pre>";
foreach (headers_list() as $header) {
echo htmlspecialchars($header) . "\n";
}
echo "</pre>";
}
// ヘッダーを設定
header("Content-Type: text/html; charset=UTF-8");
header("X-Debug-Mode: true");
// 開発環境でのみヘッダー情報を表示
if ($_SERVER['SERVER_NAME'] === 'localhost') {
debug_headers();
}
?>
条件付きヘッダー設定
<?php
// 特定のヘッダーが既に設定されているかチェック
function isHeaderSet($headerName) {
$headers = headers_list();
foreach ($headers as $header) {
if (stripos($header, $headerName . ':') === 0) {
return true;
}
}
return false;
}
// Content-Typeが設定されていない場合のみ設定
if (!isHeaderSet('Content-Type')) {
header("Content-Type: text/html; charset=UTF-8");
}
// カスタムヘッダーの重複チェック
if (!isHeaderSet('X-API-Version')) {
header("X-API-Version: 1.0");
}
?>
APIレスポンスでの活用例
<?php
function sendApiResponse($data, $status = 200) {
// レスポンスコードを設定
http_response_code($status);
// 基本的なAPIヘッダーを設定
header("Content-Type: application/json; charset=UTF-8");
header("X-API-Version: 2.0");
header("Access-Control-Allow-Origin: *");
// デバッグモードの場合、ヘッダー情報も含める
if (defined('DEBUG_MODE') && DEBUG_MODE) {
$response = [
'data' => $data,
'debug' => [
'headers' => headers_list(),
'timestamp' => date('Y-m-d H:i:s')
]
];
} else {
$response = ['data' => $data];
}
echo json_encode($response, JSON_UNESCAPED_UNICODE);
exit();
}
// 使用例
$userData = ['name' => '田中太郎', 'age' => 30];
sendApiResponse($userData);
?>
まとめ
header関数は、PHPでWebアプリケーションを開発する上で欠かせない重要な関数です。headers_list()
関数と組み合わせることで、より効果的なヘッダー管理とデバッグが可能になります。
重要なポイントをもう一度整理すると:
- 出力前に実行することが最重要
- リダイレクト後は
exit()
を忘れずに - セキュリティ対策を怠らない
- 用途に応じて適切なヘッダーを設定する
headers_list()
でデバッグや条件分岐を効率化
これらのポイントを押さえて、header関数とheaders_list関数を効果的に活用してください。実際の開発では、様々なケースに応じてこれらの関数を使い分けることで、ユーザビリティとセキュリティの両方を向上させることができます。