web-dev-qa-db-ja.com

「Headers already sent」のエラーを修正する方法 PHP

スクリプトを実行すると、次のようなエラーがいくつか発生しています。

Warning:ヘッダ情報は変更できません - /some/file.php onの(outputは/some/file.php:12で開始されています)によって既に送信されているヘッダ23行目

エラーメッセージに記載されている行には、 header() および setcookie() が含まれています。

その理由は何でしょうか。そしてどのようにそれを修正するのですか?

835
Moses89

ヘッダーを送信する前に出力がありません!

HTTPヘッダーを送信/変更する関数を呼び出す必要があります出力を行う前に。 summary ⇊ そうでない場合、呼び出しは失敗します。

警告:ヘッダー情報を変更できません-ヘッダーは既に送信されています(出力は script:line

HTTPヘッダーを変更する関数は次のとおりです。

出力は次のとおりです。

  • 意図的:

    • printecho、および出力を生成するその他の関数
    • <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>

ページ/出力は常にfollowsヘッダーです。 PHPは最初にヘッダーをWebサーバーに渡す必要があります。それは一度しかできません。二重改行の後、それらを修正することはできません。

PHPが最初の出力(printecho<html>)を受け取ると、flush収集されたすべてのヘッダーになります。その後、必要なすべての出力を送信できます。しかし、それ以上HTTPヘッダーを送信することは不可能です。

早すぎる出力がどこで発生したかをどのようにして見つけることができますか?

header()警告には、問題の原因を特定するためのすべての関連情報が含まれています。

警告:ヘッダー情報を変更できません-(output started at/ www/usr2345/htdocs /によって送信されたヘッダーauth.php:52)/www/usr2345/htdocs/index.phpの100行目

ここで、「行100」は、header()invocationが失敗したスクリプトを指します。

括弧内の「output started at」の注記の方が重要です。前の出力のソースを指定します。この例では、auth.phpline 52です。ここで、早すぎる出力を探す必要がありました。

典型的な原因:

  1. 印刷、エコー

    printおよびechoステートメントからの意図的な出力により、HTTPヘッダーを送信する機会が終了します。これを回避するには、アプリケーションフローを再構築する必要があります。 functions およびテンプレートスキームを使用します。 header()呼び出しが発生することを確認しますbeforeメッセージが書き出されます。

    出力を生成する関数には次が含まれます

    • printechoprintfvprintf
    • trigger_errorob_flushob_end_flushvar_dumpprint_r
    • readfilepassthruflushimagepngimagejpeg


    その他およびユーザー定義関数。

  2. 生のHTMLエリア

    .phpファイル内の未解析のHTMLセクションも直接出力されます。 header()呼び出しをトリガーするスクリプト条件は、any raw <html>ブロックの前に注意する必要があります。

    <!DOCTYPE html>
    <?php
        // Too late for headers already.
    

    テンプレートスキームを使用して、処理を出力ロジックから分離します。

    • フォーム処理コードをスクリプトの上に配置します。
    • 一時的な文字列変数を使用して、メッセージを延期します。
    • 実際の出力ロジックと混合HTML出力は最後に従う必要があります。

  3. 「script.phpline 1」警告の<?phpの前の空白

    警告が行の出力1を参照している場合、ほとんどの場合は先行whitespace、開始<?phpトークンの前のテキストまたはHTML。

     <?php
    # There's a SINGLE space/newline before <? - Which already seals it.
    

    同様に、追加されたスクリプトまたはスクリプトセクションで発生する可能性があります。

    ?>
    
    <?php
    

    PHPは実際には、終了タグの後にsingle改行を使い果たします。ただし、複数の改行、タブ、またはそのようなギャップにシフトされたスペースは補正されません。

  4. UTF-8 BOM

    改行とスペースだけが問題になる場合があります。しかし、これを引き起こす可能性のある「見えない」文字シーケンスもあります。最も有名なのは UTF-8 BOM(Byte-Order-Mark) であり、ほとんどのテキストエディターでは表示されません。これはバイトシーケンスEF BB BFであり、UTF-8でエンコードされたドキュメントではオプションであり、冗長です。 PHPただし、生の出力として扱う必要があります。出力(クライアントがドキュメントをLatin-1として解釈する場合)または同様の「ガベージ」に文字として表示される場合があります。

    特に、グラフィカルエディタとJavaベースのIDEは、その存在を忘れています。彼らはそれを視覚化しません(Unicode標準で義務付けられています)。ただし、ほとんどのプログラマーおよびコンソールエディターは以下を実行します。

    joes editor showing UTF-8 BOM placeholder, and MC editor a dot

    そこで、問題を早期に簡単に認識できます。他の編集者は、ファイル/設定メニューでその存在を特定する場合があります(WindowsのNotepad ++は特定できます 問題の修正 )、BOMの存在を検査する別のオプションはhexeditor * nixシステムでは hexdump が通常使用可能ですが、そうでない場合は、これらの問題やその他の問題の監査を簡素化するグラフィカルなバリアントです。

    beav hexeditor showing utf-8 bom

    簡単な修正方法は、ファイルを「UTF-8(BOMなし)」または同様の命名法で保存するようにテキストエディターを設定することです。多くの場合、新規参入者は新しいファイルを作成し、以前のコードをコピーして貼り付けるだけです。

    修正ユーティリティ 

    テキストファイルを調べて書き換える自動化ツールもあります( sed/awk またはrecode)。 PHPには、具体的には phptags tag tidier があります。クローズタグとオープンタグを長い形式と短い形式に書き換えますが、先頭と末尾の空白、Unicode、UTF-x BOMの問題も簡単に修正します

    phptags  --whitespace  *.php
    

    インクルードディレクトリまたはプロジェクトディレクトリ全体で使用するのは正気です。

  5. ?>の後の空白

    エラーソースが close ?> の背後にあると記載されている場合、ここで空白または生のテキストが書き出されます。 PHP終了マーカーは、この時点でスクリプトの実行を終了しません。それ以降のテキスト/スペース文字は、まだページコンテンツとして書き出されます。

    特に新参者には、末尾の?> PHP closeタグを省略することをお勧めします。 eschewsこれらのケースのごく一部。 (非常に一般的なinclude()dスクリプトが原因です。)

  6. 「行0で不明」と記載されているエラーソース

    エラーソースが具体化されていない場合、通常はPHP拡張機能またはphp.ini設定です。

    • 時折、gzipストリームエンコーディング設定 またはob_gzhandler です。
    • しかし、暗黙的にPHP起動/警告メッセージを生成する二重にロードされたextension=モジュールでもかまいません。

  7. 前のエラーメッセージ

    別のPHPステートメントまたは式によって警告メッセージまたは通知が出力される場合、それも早期出力としてカウントされます。

    この場合、エラーを回避するか、ステートメントの実行を遅らせるか、メッセージを抑制する必要があります。 isset() または @() -どちらかが後でデバッグを妨げない場合.

エラーメッセージなし

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 出力バッファリング は、この問題を軽減する回避策です。多くの場合、確実に機能しますが、アプリケーションを適切に構造化し、出力を制御ロジックから分離する代わりにすべきではありません。実際の目的は、ウェブサーバーへのチャンク転送を最小限にすることです。

  1. それでも、 output_buffering= 設定が役立ちます。 php.ini で設定するか、または 。htaccess で設定するか、最新のFPM/FastCGIセットアップで 。user.ini で設定します。
    有効にすると、PHPが即座にWebサーバーに出力を渡すのではなく、出力をバッファリングできます。したがって、PHPはHTTPヘッダーを集約できます。

  2. 同様に、呼び出しスクリプトの上で ob_start(); を呼び出すこともできます。ただし、これは複数の理由により信頼性が低くなります。

    • <?php ob_start(); ?>が最初のスクリプトを開始したとしても、空白またはBOMがシャッフルされる可能性があります レンダリングを無効にする

    • HTML出力の空白を隠すことができます。ただし、アプリケーションロジックがバイナリコンテンツ(生成されたイメージなど)を送信しようとするとすぐに、バッファリングされた外部出力が問題になります。 (さらに回避策としてob_clean()が必要です。)

    • バッファのサイズには制限があり、デフォルトのままにすると簡単にオーバーランする可能性があります。そして、それはまれな出来事でもありません 追跡するのが難しい それが起こるとき。

したがって、両方のアプローチは信頼性が低くなる可能性があります-特に、開発セットアップと実稼働サーバー間で切り替える場合。出力バッファリングが広く松葉杖/厳密に回避策と広く考えられている理由です。

マニュアルの 基本的な使用例 も参照してください。長所と短所については、以下を参照してください。

しかし、他のサーバーでは機能しました!?

以前にヘッダーの警告が表示されなかった場合、 出力バッファリング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設定などにも依存します。)

その他のリンク

2884
mario

このエラーメッセージは、HTTPヘッダーを送信する前にanythingが送信されたときにトリガーされます( setcookie または header =)。 HTTPヘッダーの前に何かを出力する一般的な理由は次のとおりです。

  • 多くの場合、ファイルの先頭または末尾にある次のような偶発的な空白。

     <?php
    // Note the space before "<?php"
    ?>
    

これを避けるには、単純に終了?>を省いてください-とにかく必須ではありません。

  • バイトオーダーマーク phpファイルの先頭。 16進エディターでphpファイルを調べて、そうであるかどうかを調べます。これらは、3F 3Cバイトで始まる必要があります。ファイルの先頭からBOM EF BB BFを安全に削除できます。
  • echoprintfreadfilepassthru<?の前のコードなどの明示的な出力.
  • display_errors php.iniプロパティが設定されている場合、phpが出力する警告。プログラマのミスでクラッシュする代わりに、PHPはエラーを静かに修正し、警告を発します。 display_errors または error_reporting 設定を変更できますが、むしろ問題を修正する必要があります。
    一般的な理由は、配列の未定義の要素へのアクセス(入力が設定されているかどうかをテストするために empty または isset を使用しない$_POST['input']など)、または文字列リテラルの代わりに未定義の定数($_POST[input]のように、引用符がないことに注意してください)。

出力バッファリング をオンにすると、問題は解消されます。 ob_start の呼び出し後のすべての出力は、バッファを解放するまでメモリにバッファされます。 ob_end_flush で。

ただし、出力バッファリングは問題を回避しますが、アプリケーションがHTTPヘッダーの前にHTTP本文を出力する理由を実際に判断する必要があります。それは電話をかけ、あなたの日と天気について話し合ってから、発信者に電話番号が間違っていることを伝えるようなものです。

192
phihag

私は何度もこのエラーに遭遇しました。そして、すべてのPHPプログラマーが少なくとも一度はこのエラーを経験したと確信しています。このエラーを解決するために、あなたはあなたの問題レベルによってuse solutionを解決することができます:

考えられる解決策1:

あなたは空白のbeforeあるいはafter(ファイルの最後に?>)を空白のままにしているかもしれません。

THERE SHOULD BE NO BLANK SPACES HERE
<?php  

   echo "your code here";

?>
DO CHECK FOR BLANK SPACES HERE AS WELL; THIS LINE (blank line) SHOULD NOT EXIST.

ほとんどの場合、これはあなたの問題を解決するはずです。ファイルyou requireに関連するすべてのファイルをチェックします。

注:gedit(デフォルトのLinuxエディター)のようなEDITOR(IDE)が保存ファイルに1行の空白行を追加することがあります。これは起こりません。あなたがLinuxを使っているなら。ページの最後の?>の後ろにあるスペースや行を削除するには、VIエディタを使用します。

そうでない場合は、次に示すように、出力バッファリングに ob_start を使用できます。

考えられる解決策2:

<?php
  ob_start();

  // code 

 ob_end_flush();
?> 

これにより、出力バッファリングがオンになり、ページがバッファリングされた後にヘッダーが作成されます。

110

下の行の代わりに

//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

それは間違いなくあなたの問題を解決します。私は同じ問題に直面しましたが、私は上記の方法でヘッダー位置を書くことによって解決しました。

80
Ipsita Rout

あなたがやる

printf ("Hi %s,</br />", $name);

クッキーを設定する前に、これは許可されていません。空白行でなくても、ヘッダの前に出力を送ることはできません。

39
Seth Carnegie

それはこの行のためです:

printf ("Hi %s,</br />", $name);

ヘッダを送る前に print/echo なにもしてはいけません。

32
Sarfraz

一般的な問題

(コピー元: source

====================

1)header(.......);コマンドの前に何も出力(例:echo..またはHTMLコード)があってはいけません。

2)<?phpタグの前および?>タグの後にあるすべての空白(またはnewline)を削除します。

3)GOLDEN RULE! - そのphpファイル(そしてあなたが他のファイルをinclude)にUTF8がBOMでエンコードされていないかチェックします(UTF-8だけではありません)。これは多くの場合問題です(なぜならUTF8でエンコードされたファイルはphpファイルの先頭に何か特別な文字があり、それはあなたのテキストエディタでは表示されないからです)!!!!!!!!!!

4)header(...);の後はexit;を使わなければなりません

5)は常に301または302の参照を使用します。

header("location: http://example.com",  true,  301 );  exit;

6)エラー報告をオンにして、エラーを見つけます。あなたのエラーは、機能していない機能が原因である可能性があります。エラー報告を有効にするときは、常に最上位エラーを最初に修正する必要があります。たとえば、「Warning:date_default_timezone_get():システムのタイムゾーン設定に頼るのは安全ではありません」のようになります。 - さらに先に進むと、「ヘッダが送信されていません」というエラーが表示される場合があります。一番上(1)のエラーを修正した後、ページを再読み込みしてください。それでもエラーが発生する場合は、一番上のエラーをもう一度修正してください。

7)上記のいずれでも解決しない場合は、JAVSCRIPTリダイレクトを使用してください(ただし、強くお勧めしない方法)。カスタムケースでは最後のチャンスかもしれません...:

echo "<script type='text/javascript'>window.top.location='http://website.com/';</script>"; exit;
28
Jorn

簡単なヒント:スクリプトの最初の<?phpタグの直前に、単純なスペース(または見えない特殊文字)があるとこれが起こる可能性があります。特にあなたがチームで働いていて、誰かが「弱い」IDEを使っているか、ファイルに奇妙なテキストエディタが散らばっている場合は特にそうです。

私はこれらのことを見ました;)

26
Sliq

もう一つの悪い習慣はまだ述べられていないこの問題を引き起こすことができます。

このコードスニペットを参照してください。

<?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でなければなりません。
  • 終了?>タグはonly phpを含むファイルからのomittedでなければなりません

私を信じて、これらの基準に従うことはあなたの人生からあなたに地獄の時間を節約することができます:)

21

DevプロセスがWINワークステーションとLINUXシステム(ホスティング)の両方を持っていて、関連する行の前に何も出力されていないコードでは、ファイルのフォーマットと Unix LF(改行) 行の終わり。

これをすばやく修正するために通常行うことは、ファイルの名前を変更し、LINUXシステムで名前を変更したファイルの代わりに新しいファイルを作成して、その中にコンテンツをコピーすることです。一度、ホスティングに移動されたWINで作成されたファイルのいくつかがこの問題を引き起こすので、多くの場合これは問題を解決します。

この修正は、FTPで管理しているサイトを簡単に修正するものであり、新しいチームメンバーの時間を節約することができます。

15
Lupin

一般に、このエラーはエコーまたは印刷後にヘッダを送信したときに発生します。このエラーが特定のページで発生した場合は、そのページが何もエコーしていないことを確認してからstart_session()を呼び出してください。

予測不可能なエラーの例:

 <?php //a white-space before <?php also send for output and arise error
session_start();
session_regenerate_id();

//your page content

もう一つの例:

<?php
includes 'functions.php';
?> <!-- This new line will also arise error -->
<?php
session_start();
session_regenerate_id();

//your page content

結論:session_start()またはheader()関数を呼び出す前に、空白や改行でなくても文字を出力しないでください。

2