PHP cannot modify header information – headers already sent エラーについて解説
PHPで表示される「php cannot modify header information – headers already sent」エラーは、出力処理が始まった後にHTTPヘッダーの変更を試みると発生します。
空白や改行などが原因の場合が多く、原因箇所の特定と修正が求められます。
この記事では、エラー発生の背景と具体的対策についてわかりやすく解説します。
エラー原因の確認
PHPのヘッダー送信メカニズム
HTTPヘッダー送信タイミングの基本
PHPでは、HTTPヘッダーは最初の出力が実行された時点でクライアントに送信されます。
そのため、スクリプト内で何らかの文字列やHTML、空白が出力された後にheader()
関数を利用しようとすると、すでにヘッダーが送信されている状態となり、エラーが発生します。
例えば、下記のサンプルコードでは、echo
によって出力が始まった後でリダイレクト処理を行っているため、エラー「PHP cannot modify header information – headers already sent」が発生します。
<?php
// 出力開始前にヘッダーを送信するべき場合のサンプルコード
echo "初期出力"; // ここで出力が開始される
// この時点でヘッダーはすでに送信済みなのでエラーとなる
header("Location: redirect.php"); // リダイレクトヘッダーを送ろうとする
?>
Warning: Cannot modify header information - headers already sent by (output started at /path/to/script.php:3) in /path/to/script.php on line 6
出力処理とヘッダーの関係
PHPの出力はバッファに貯められる場合もありますが、出力バッファリングが無効の場合は、ファイル内のどこかで出力が行われた時点でヘッダーも確定してしまいます。
これは、例えばHTMLや単純な改行、空白を含む場合にも同様です。
出力バッファリングを活用すれば、出力を一時的に保持し、ヘッダーを正しく送信してから内容を出力することが可能です。
下記のサンプルコードは出力バッファリングを使用して、ヘッダー送信前に不要な出力を防ぐ方法を示しています。
<?php
// 出力バッファリングを開始する
ob_start();
// 出力前にヘッダーを送信
header("Location: redirect.php");
// バッファの内容をクリア
ob_end_clean();
?>
(この場合、リダイレクト処理が正常に実行され、出力自体は行われません。)
不要出力の影響
PHP開始タグ前後の空白・改行
ファイルの先頭やPHPの終了タグ(?>)以降に不要な空白や改行があると、これらが出力とみなされることがあります。
特に、外部のエディタで作業する場合、エディタが自動的に余計な改行を付与することがあるため、注意が必要です。
出力が自動で開始されると、後続のheader()
処理が失敗してしまいます。
ファイルの先頭にBOMが含まれていると同様の問題が発生するため、エディタの設定でBOM無しのUTF-8形式にすることが推奨されます。
ファイルエンコーディング(BOM)の影響
BOM(Byte Order Mark)が付加されたファイルは、PHPが読み込みを開始した瞬間に不可視の文字列を出力してしまう場合があります。
これにより、ヘッダー送信前にすでに出力が行われたと見なされるため、エラーが発生することになります。
エディタでファイルのエンコーディングを確認し、BOM無しで保存するように心がけると良いでしょう。
発生状況の検証
スクリプト内出力箇所の確認
HTML出力・エラーメッセージの混在
スクリプト内に直接HTMLを出力するコードと、エラーや警告が同じ出力バッファに混在する場合、予期せぬタイミングでヘッダーの送信が完了してしまうことがあります。
HTML出力が先に発生すると、その後のヘッダー設定が不可能になりエラーが発生します。
下記のサンプルコードは、HTML出力の前にヘッダーを設定する方法と、設定が被らないように注意する点を示しています。
<?php
// ヘッダー送信はHTML出力前に実施する必要がある
header("Content-Type: text/html; charset=UTF-8");
// HTML出力
echo "<!DOCTYPE html>";
echo "<html><head><title>テストページ</title></head><body>";
echo "<p>サンプルページです。</p>";
echo "</body></html>";
?>
(HTMLページが正しく表示され、エラーは発生しません。)
コメント等による不要出力
PHPのコメント自体は出力されませんが、PHP終了タグの直後に記述された改行や空白は出力と判断されます。
スクリプト内でコメントを記述する場合でも、PHP終了タグを使用せずにファイルを完結させる方法が推奨されます。
これにより、意図しない出力を避けることができます。
以下のサンプルコードは、PHP終了タグを削除した形で記述しています。
<?php
// 出力前に必ずヘッダーを送信する処理を書く
header("X-Custom-Header: Value");
// コードコメント
echo "必要な出力のみを記述";
// PHP終了タグを省略して意図しない出力を防ぐ
(出力結果は「必要な出力のみを記述」となります。)
環境設定の点検
PHPバージョンの確認
PHPのバージョンによっては、出力バッファリングの動作やheader()
関数の扱いに違いがある場合があります。
特定のバージョンにてのみ発生する問題があるため、開発環境のPHPバージョンを確認し、使用しているバージョンに固有の既知問題や仕様変更がないかをチェックすることが重要です。
php.ini設定の見直し
php.ini
の設定で、出力バッファリングの有効/無効や、エラーレベル、タイムゾーンなどが設定されています。
特に、output_buffering
が有効になっていれば、出力が一時的にバッファに保持されるため、意図せずヘッダー送信エラーを回避できるケースがあります。
しかし、実際の運用においては、コード内で明示的にバッファリングを制御する方が確実です。
必要に応じて、php.ini
の設定を確認し、適切な値に変更するよう注意してください。
修正手順と対策
出力制御の再構築
出力バッファリングの活用方法
出力バッファリングを利用することで、ヘッダー送信前にすべての出力を保持することができます。
これにより、意図しないタイミングでヘッダーが送信されるのを防ぐことができます。
以下に、出力バッファリングを利用するサンプルコードを示します。
<?php
// 出力バッファリングを開始
ob_start();
// ヘッダー送信は出力が行われる前に実施
header("Content-Type: text/plain");
// 必要な出力内容を生成
echo "バッファに出力内容を保持";
// 出力をバッファから一括して出力
ob_end_flush();
?>
バッファに出力内容を保持
不要な出力の整理方法
コード全体を見直し、不要な空白や改行、意図しない出力箇所を整理することが重要です。
特に、以下の点に注意してください。
- PHP開始タグ直後に不要な空白・改行がないか確認する。
- PHP終了タグ(?>)を使用しないようにする。
- 外部ライブラリやインクルードファイル内の不要な出力をチェックする。
ヘッダー送信タイミングの調整
ヘッダー送信前の処理順序確認
ヘッダー送信処理と出力処理の順序を明確に分離することが重要です。
ヘッダーはすべての出力が行われる前に送信される必要があります。
そのため、ヘッダー送信に必要な処理をスクリプトの最初の方にまとめるよう心がけると、問題を未然に防止できます。
下記のサンプルコードは、ヘッダー送信前にすべての必要な設定を行う方法を示しています。
<?php
// スクリプトの最初にヘッダーをすべて設定する
header("Content-Type: application/json; charset=UTF-8");
// 必要な初期設定や変数定義をここで実施
$response = [
"status" => "success",
"message" => "ヘッダー送信前の処理が完了"
];
// 出力前にjsonエンコードし、ヘッダー送信後に出力
echo json_encode($response);
?>
{"status":"success","message":"ヘッダー送信前の処理が完了"}
修正後の動作検証ポイント
ヘッダー送信の問題を修正した後は、実際の動作検証を行うことが重要です。
以下の点を確認してください。
- リダイレクトやコンテンツタイプ変更など、ヘッダーが正常に送信されるか。
- 出力の順序が意図通りになっているか。
- 予期しない出力(空白や改行など)がないか。
これらの確認項目について、手動テストや自動化テストを活用して、修正が正しく反映されているかを検証してください。
まとめ
この記事では、PHPのヘッダー送信エラーの原因、検証方法および対策について詳しく解説しました。
全体を通じても、出力の管理とヘッダー送信順序の重要性が理解できる内容となっています。
今すぐコードを整理し、出力バッファリングの活用を試してみてください。