PHPで「ヘッダーがすでに送信されました」エラーを修正する方法
スクリプトを実行すると、次のようなエラーが発生します。
警告:ヘッダー情報を変更することはできません-すでに(によって送られたヘッダ/some/file.php:12で開始出力に)/some/file.phpにライン23を
エラーメッセージに記載されている行にはheader()、とsetcookie()が含まれています。
これの理由は何でしょうか?そしてそれを修正する方法は?
回答
ヘッダーを送信する前に出力はありません!
HTTPヘッダーを送信/変更する関数は、出力を行う前に呼び出す必要があります。summary ⇊それ以外の場合、呼び出しは失敗します。
警告:ヘッダー情報を変更できません-ヘッダーはすでに送信されています(出力はscript:lineで開始されます)
HTTPヘッダーを変更するいくつかの関数は次のとおりです。
- header / header_remove
- session_start / session_regenerate_id
- setcookie / setrawcookie
出力は次のようになります。
意図的ではない:
- 空白の前
<?php
または後?>
- UTF-8バイトオーダーマーク、具体的
- 以前のエラーメッセージまたは通知
- 空白の前
意図的:
print
、echo
および出力を生成するその他の関数- 生の
<html>
セクションの前の<?php
コード。
なぜそれが起こるのですか?
出力の前にヘッダーを送信する必要がある理由を理解するには、一般的なHTTP応答を確認する必要があります。PHPスクリプトは主にHTMLコンテンツを生成しますが、HTTP / CGIヘッダーのセットをWebサーバーに渡します。
HTTP/1.1 200 OK
Powered-By: PHP/5.3.7
Vary: Accept-Encoding
Content-Type: text/html; charset=utf-8
<html><head><title>PHP page output page</title></head>
<body><h1>Content</h1> <p>Some more output follows...</p>
and <a href="/"> <img src=internal-icon-delayed> </a>
ページ/出力は常にヘッダーの後に続きます。PHPは、最初にヘッダーをWebサーバーに渡す必要があります。それは一度しかできません。二重の改行の後、それはもはやそれらを修正することはできません。
PHPは、第一の出力を受信すると(print
、echo
、<html>
)それがあろう洗い流す収集されたすべてのヘッダー。その後、必要なすべての出力を送信できます。しかし、それ以上のHTTPヘッダーを送信することは不可能です。
早すぎる出力が発生した場所をどのように見つけることができますか?
header()
警告は、問題の原因を特定するために、関連するすべての情報が含まれています。
警告:ヘッダー情報を変更することはできません-ヘッダが既にによって送信された(で開始出力/ WWW / usr2345 / htdocsに/ auth.php:52)は、ライン100上で/www/usr2345/htdocs/index.php
ここで、「100行目」は、header()
呼び出しが失敗したスクリプトを指します。
括弧内の「出力開始」の注記はより重要です。これは、前の出力のソースを示します。この例では、それはだauth.php
とライン52
。ここで、時期尚早の出力を探す必要がありました。
典型的な原因:
印刷、エコー
print
およびecho
ステートメントからの意図的な出力により、HTTPヘッダーを送信する機会が終了します。これを回避するには、アプリケーションフローを再構築する必要があります。関数とテンプレートスキームを使用します。メッセージが書き出される前にheader()
呼び出しが発生することを確認してください。出力を生成する関数は次のとおりです。
print
、echo
、printf
、vprintf
trigger_error
、ob_flush
、ob_end_flush
、var_dump
、print_r
readfile
、passthru
、flush
、imagepng
、imagejpeg
とりわけ、ユーザー定義関数。生のHTML領域
.php
ファイル内の未解析のHTMLセクションも直接出力されます。header()
呼び出しをトリガーするスクリプト条件は、 raw<html>
ブロックの前に注意する必要があります。<!DOCTYPE html> <?php // Too late for headers already.
テンプレートスキームを使用して、処理を出力ロジックから分離します。
- フォーム処理コードをスクリプトの上に配置します。
- 一時的な文字列変数を使用してメッセージを延期します。
- 実際の出力ロジックと混合HTML出力は最後に続く必要があります。
<?php
「script.php1行目」の警告の前の空白警告が行の出力に言及している場合、
1
それはほとんどの場合、開始トークンの前の先頭の空白、テキスト、またはHTML<?php
です。<?php # There's a SINGLE space/newline before <? - Which already seals it.
同様に、追加されたスクリプトまたはスクリプトセクションでも発生する可能性があります。
?> <?php
PHPは、タグを閉じると、実際には1つの改行を消費します。ただし、そのようなギャップにシフトされた複数の改行、タブ、またはスペースは補正されません。
UTF-8 BOM
改行とスペースだけが問題になる可能性があります。しかし、これを引き起こす可能性のある「見えない」文字シーケンスもあります。最も有名なのは、ほとんどのテキストエディタで表示されないUTF-8 BOM(Byte-Order-Mark)です。これはバイトシーケンス
EF BB BF
であり、UTF-8でエンコードされたドキュメントではオプションで冗長です。ただし、PHPはそれを生の出力として扱う必要があります。
出力(クライアントがドキュメントをLatin-1として解釈する場合)または同様の「ガベージ」の文字として表示される場合があります。特に、グラフィカルエディタとJavaベースのIDEは、その存在に気づいていません。彼らはそれを視覚化しません(Unicode標準によって義務付けられています)。ただし、ほとんどのプログラマーおよびコンソールエディターは次のことを行います。
そこでは、問題を早期に認識するのは簡単です。他のエディターは、ファイル/設定メニューでその存在を識別できます(WindowsのNotepad ++は問題を識別して修正できます)、BOMの存在を検査する別のオプションは、16進エディターに頼ることです。* nixシステムでhexdumpは、これらの問題やその他の問題の監査を簡素化するグラフィカルなバリアントではないにしても、通常は利用可能です。
簡単な修正は、ファイルを「UTF-8(BOMなし)」または同様の命名法で保存するようにテキストエディタを設定することです。それ以外の場合、新規参入者は新しいファイルを作成し、前のコードをコピーして貼り付けるだけで済みます。
修正ユーティリティ
テキストファイル(sed/awkまたは
recode
)を調べて書き換えるための自動化されたツールもあります。特にPHPの場合、phptagsタグtidierがあります。クローズタグとオープンタグを長い形式と短い形式に書き換えるだけでなく、先頭と末尾の空白、Unicode、およびUTF-xBOMの問題を簡単に修正します。phptags --whitespace *.php
インクルードディレクトリまたはプロジェクトディレクトリ全体で使用するのは正気です。
後の空白
?>
エラーの原因がクロージングの?>背後にあると言及されている場合、これは空白または生のテキストが書き出された場所です。PHP終了マーカーは、この時点ではスクリプトの実行を終了しません。それ以降のテキスト/スペース文字は、引き続きページコンテンツとして書き出されます。
特に初心者には、末尾の
?>
PHPクローズタグを省略することをお勧めします。これにより、これらのケースのごく一部が回避されます。(非常に一般的にinclude()d
は、スクリプトが原因です。)「0行目で不明」と記載されているエラーソース
エラーソースが具体化されていない場合、これは通常、PHP拡張機能またはphp.ini設定です。
- それは時折だ
gzip
ストリームのエンコードの設定やob_gzhandler。 - しかし、それは
extension=
、暗黙のPHP起動/警告メッセージを生成する二重にロードされたモジュールである可能性もあります。
- それは時折だ
先行するエラーメッセージ
別のPHPステートメントまたは式によって警告メッセージまたは通知が出力される場合、それも時期尚早の出力としてカウントされます。
この場合、エラーを回避するか、ステートメントの実行を遅らせるか、またはメッセージをegisset()または@()-で抑制して、後でデバッグを妨げないようにする必要があります。
エラーメッセージはありません
を持っているerror_reporting
かdisplay_errors
無効にしている場合php.ini
、警告は表示されません。ただし、エラーを無視しても問題は解決しません。早すぎる出力の後でも、ヘッダーを送信することはできません。
したがって、header("Location: ...")
リダイレクトがサイレントに失敗した場合は、警告をプローブすることをお勧めします。呼び出しスクリプトの上にある2つの簡単なコマンドでそれらを再度有効にします。
error_reporting(E_ALL);
ini_set("display_errors", 1);
またはset_error_handler("var_dump");
、他のすべてが失敗した場合。
リダイレクトヘッダーと言えば、最終的なコードパスには次のようなイディオムを使用する必要があります。
exit(header("Location: /finished.html"));
できれば、header()
障害が発生した場合にユーザーメッセージを出力するユーティリティ関数ですら。
回避策としての出力バッファリング
PHPの出力バッファリングは、この問題を軽減するための回避策です。多くの場合、確実に機能しますが、適切なアプリケーションの構造化と制御ロジックからの出力の分離に代わるものではありません。その実際の目的は、Webサーバーへのチャンク転送を最小限に抑えることです。
output_buffering=それにもかかわらず、設定は役に立ちます。最新のFPM / FastCGIセットアップでは、php.iniで、または.htaccessまたは.user.iniを介して構成します。
これを有効にすると、PHPは出力をWebサーバーに即座に渡すのではなく、バッファリングできるようになります。したがって、PHPはHTTPヘッダーを集約できます。同様ob_start();に、呼び出しスクリプトの上への呼び出しを行うこともできます。ただし、これは複数の理由で信頼性が低くなります。
<?php ob_start(); ?>
最初のスクリプトを開始した場合でも、空白またはBOMが以前にシャッフルされ、無効になる可能性があります。HTML出力の空白を隠すことができます。ただし、アプリケーションロジックがバイナリコンテンツ(生成された画像など)を送信しようとするとすぐに、バッファリングされた無関係な出力が問題になります。(
ob_clean()
さらなる回避策として必要です。)バッファのサイズは制限されており、デフォルトのままにすると簡単にオーバーランする可能性があります。そして、それも珍しいことではなく、発生したときに追跡するのは困難です。
したがって、両方のアプローチは、特に開発セットアップや本番サーバーを切り替えるときに、信頼性が低くなる可能性があります。そのため、出力バッファリングは単なる松葉杖/厳密な回避策と広く見なされています。
マニュアルの基本的な使用例、およびその他の長所と短所も参照してください。
- 出力バッファリングとは何ですか?
- PHPで出力バッファリングを使用する理由
- 出力バッファリングの使用は悪い習慣と見なされていますか?
- 「すでに送信されたヘッダー」の正しい解決策としての出力バッファリングのユースケース
しかし、それは他のサーバーで動作しました!?
以前にヘッダーの警告が表示されなかった場合は、出力バッファリングのphp.ini設定が変更されています。現在の/新しいサーバーでは構成されていない可能性があります。
で確認する headers_sent()
headers_sent()それでもヘッダーを送信できるかどうかを調べるために、いつでも使用できます。これは、条件付きで情報を印刷したり、他のフォールバックロジックを適用したりするのに役立ちます。
if (headers_sent()) {
die("Redirect failed. Please click on this link: <a href=...>");
}
else{
exit(header("Location: /user.php"));
}
便利なフォールバック回避策は次のとおりです。
HTML
<meta>
タグアプリケーションを構造的に修正するのが難しい場合、リダイレクトを許可する簡単な(しかしやや専門的ではない)方法は、HTML
<meta>
タグを挿入することです。リダイレクトは次の方法で実現できます。<meta http-equiv="Location" content="http://example.com/">
または少し遅れて:
<meta http-equiv="Refresh" content="2; url=../target.html">
これにより、
<head>
セクションを超えて使用すると、HTMLが無効になります。ほとんどのブラウザはまだそれを受け入れます。JavaScriptリダイレクト
別の方法として、JavaScriptリダイレクトをページリダイレクトに使用できます。
<script> location.replace("target.html"); </script>
これは多くの場合、
<meta>
回避策よりもHTMLに準拠していますが、JavaScript対応のクライアントに依存することになります。
ただし、どちらのアプローチも、正規のHTTP header()呼び出しが失敗した場合に許容可能なフォールバックを行います。理想的には、最後の手段として、これを常にユーザーフレンドリーなメッセージとクリック可能なリンクと組み合わせるでしょう。(これは、たとえばhttp_redirect() PECL拡張機能が行うことです。)
なぜsetcookie()
そしてsession_start()
また影響を受ける
両方setcookie()
とsession_start()
必要送信するSet-Cookie:
HTTPヘッダーを。したがって、同じ条件が適用され、出力が早すぎる状況でも同様のエラーメッセージが生成されます。
(もちろん、ブラウザで無効になっているCookieや、プロキシの問題によっても影響を受けます。セッション機能は、明らかに空きディスク容量やその他のphp.ini設定などにも依存します。)
その他のリンク
- グーグルは同様の議論の長いリストを提供します。
- そしてもちろん、多くの特定のケースがStackOverflowでもカバーされています。
- WordpressのFAQでは、すでに送信されたヘッダーの警告の問題を解決するにはどうすればよいですか?一般的な方法で。
- アドビコミュニティ:PHP開発:リダイレクトが機能しない理由(ヘッダーはすでに送信されています)
- Nucleus FAQ:「ページヘッダーはすでに送信されています」とはどういう意味ですか?
- より詳細な説明の1つは、HTTPヘッダーとPHPヘッダー()関数です-NicholasSolutionsによるチュートリアル(インターネットアーカイブリンク)。HTTPについて詳しく説明し、スクリプトを書き直すためのガイドラインをいくつか示します。
このエラーメッセージは、HTTPヘッダー(またはを使用)を送信する前に何かが送信されたときにトリガーされます。HTTPヘッダーの前に何かを出力する一般的な理由は次のとおりです。setcookieheader
多くの場合、次のようにファイルの最初または最後にある偶発的な空白。
<?php // Note the space before "<?php" ?>
これを回避するには、単にクロージングを省略します?>
-とにかく必要ありません。
- phpファイルの先頭にあるバイト順マーク。phpファイルを16進エディターで調べて、それが当てはまるかどうかを確認します。それらはバイトで始まる必要があります
3F 3C
。EF BB BF
ファイルの先頭からBOMを安全に削除できます。 - このような呼び出しのような明示的な出力、
echo
、printf
、readfile
、passthru
、コードの前に<?
等 - display_errorsphp.iniプロパティが設定されている場合、phpによって出力される警告。プログラマーのミスでクラッシュする代わりに、phpはサイレントにエラーを修正し、警告を発します。display_errorsまたはerror_reporting構成を変更できますが、問題を修正する必要があります。
一般的な理由は、配列の未定義の要素へのアクセス(入力が設定されているかどうか$_POST['input']
を使用emptyまたはissetテストしないなど)、または文字列リテラルの代わりに未定義の定数を使用することです($_POST[input]
引用符がないことに注意してください)。
出力バッファリングをオンにすると、問題が解決するはずです。呼び出し後のすべての出力ob_startは、バッファを解放するまでメモリにバッファリングされます(例:ob_end_flush。
ただし、出力バッファリングは問題を回避しますが、アプリケーションがHTTPヘッダーの前にHTTPボディを出力する理由を実際に判断する必要があります。それは、電話をかけて、あなたの日と天気について話し合ってから、発信者に間違った番号を持っていることを伝えるようなものです。
私は以前に何度もこのエラーを受け取りました、そして私はすべてのPHPプログラマーが少なくとも一度はこのエラーを受け取ったと確信しています。
考えられる解決策1
このエラーは、ファイルの開始前またはファイルの終了後の空白が原因である可能性があります。これらの空白はここにあるべきではありません。
例)ここに空白のスペースがあってはなりません
echo "your code here";
?>
THERE SHOULD BE NO BLANK SPACES HERE
このエラーの原因となっているファイルに関連付けられているすべてのファイルを確認してください。
注: gedit(デフォルトのLinuxエディター)のようなEDITOR(IDE)は、保存ファイルに1行の空白行を追加することがあります。これは起こらないはずです。Linuxを使用している場合。VIエディターを使用して、ページの最後にある?>の後のスペース/行を削除できます。
考えられる解決策2:これが当てはまらない場合は、ob_startを使用してバッファリングを出力します。
<?php
ob_start();
// code
ob_end_flush();
?>
これにより、出力バッファリングがオンになり、ページがバッファリングされた後にヘッダーが作成されます。
以下の行の代わりに
//header("Location:".ADMIN_URL."/index.php");
書く
echo("<script>location.href = '".ADMIN_URL."/index.php?msg=$msg';</script>");
または
?><script><?php echo("location.href = '".ADMIN_URL."/index.php?msg=$msg';");?></script><?php
それは間違いなくあなたの問題を解決します。同じ問題に直面しましたが、上記の方法でヘッダーの場所を書き込むことで解決しました。
あなたがやる
printf ("Hi %s,</br />", $name);
クッキーを設定する前に、これは許可されていません。ヘッダーの前に出力を送信することはできません。空白行も送信できません。
一般的な問題:
(コピー元:ソース)
====================
1)コマンドのecho..
前に出力(つまりHTMLコード)があってはなりませんheader(.......);
。
2)タグの前後の空白(または改行)を削除<?php
し?>
ます。
3) ゴールデンルール!-そのphpファイル(およびinclude
他のファイルの場合)にBOMエンコードなしのUTF8があるかどうかを確認します(UTF-8だけではありません)。これは多くの場合問題です(UTF8でエンコードされたファイルのphpファイルの先頭に特殊文字が含まれているため、テキストエディターには表示されません)!!!!!!!!!!!
4)header(...);
使用する必要がある後exit;
5)常に301または302参照を使用します。
header("location: http://example.com", true, 301 ); exit;
6) エラー報告をオンにして、エラーを見つけます。エラーの原因は、機能していない機能である可能性があります。エラーレポートをオンにするときは、常に最上位のエラーを最初に修正する必要があります。たとえば、「警告:date_default_timezone_get():システムのタイムゾーン設定に依存するのは安全ではありません」のようになります。-さらに下に行くと、「ヘッダーが送信されていません」というエラーが表示される場合があります。最上位(1番目)のエラーを修正した後、ページを再ロードします。それでもエラーが発生する場合は、一番上のエラーを再度修正してください。
7)上記のいずれも役に立たない場合は、JAVSCRIPTリダイレクトを使用します(ただし、強く推奨されない方法)。カスタムケースでは最後のチャンスかもしれません...:
echo "<script type='text/javascript'>window.top.location='http://website.com/';</script>"; exit;
それはこの行のためです:
printf ("Hi %s,</br />", $name);
ヘッダーを送信する前に、何も印刷/エコーしないでください。
簡単なヒント:最初の<?php
タグの直前にあるスクリプト内の単純なスペース(または非表示の特殊文字)がこれを引き起こす可能性があります!特に、チームで作業していて、誰かが「弱い」IDEを使用している場合や、奇妙なテキストエディタでファイルをいじり回している場合は特にそうです。
私はこれらのものを見ました;)
別の悪い習慣は、まだ述べられていないこの問題を引き起こす可能性があります。
このコードスニペットを参照してください。
<?php
include('a_important_file.php'); //really really really bad practise
header("Location:A location");
?>
物事は大丈夫ですよね?
「a_important_file.php」がこれである場合はどうなりますか?
<?php
//some php code
//another line of php code
//no line above is generating any output
?>
----------This is the end of the an_important_file-------------------
これは機能しませんか?なぜですか?すでに新しい行が生成されているためです。
さて、これは一般的なシナリオではありませんが、コントローラーに物事を引き渡す前に大量のファイルをロードするMVCフレームワークを使用している場合はどうなりますか?これは珍しいシナリオではありません。これに備えてください。
PSR-2 2.2:
- すべてのPHPファイルはを使用する必要があり
Unix LF (linefeed) line ending
ます。 - すべてのPHPファイルは
single blank line
。で終わる必要があります。 - 終了タグは
omitted
、次を含むファイルからのものである必要がありますonly php
私を信じてください、これらの基準に従うことはあなたの人生からあなたに地獄の多くの時間を節約することができます:)
DEVプロセスはWINワークステーションおよびLinuxシステム(ホスティング)の両方を持っており、コードの中であなたが関連する行の前に任意の出力が表示されないとき時々 、それはファイルや不足の書式設定することができUnixのLF(改行)行末。
これをすばやく修正するために通常行うことは、ファイルの名前を変更し、LINUXシステムで名前を変更したファイルの代わりに新しいファイルを作成し、その中にコンテンツをコピーすることです。WINで作成されたファイルの一部がホスティングに移動されるとこの問題が発生するため、多くの場合、これで問題が解決します。
この修正は、FTPで管理しているサイトの簡単な修正であり、新しいチームメンバーの時間を節約できる場合があります。
通常、このエラーは、エコーまたは印刷後にヘッダーを送信するときに発生します。このエラーが特定のページで発生した場合は、を呼び出す前に、ページが何もエコーしていないことを確認してくださいstart_session()
。
予測できないエラーの例:
<?php //a white-space before <?php also send for output and arise error
session_start();
session_regenerate_id();
//your page content
もう1つの例:
<?php
includes 'functions.php';
?> <!-- This new line will also arise error -->
<?php
session_start();
session_regenerate_id();
//your page content
結論:呼び出す前に文字を出力しsession_start()
たりheader()
、空白や改行さえも機能させないでください