PHPで「ヘッダーがすでに送信されました」エラーを修正する方法

Nov 07 2011

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

警告:ヘッダー情報を変更することはできません-すでに(によって送られたヘッダ/some/file.php:12で開始出力に)/some/file.phpライン23を

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

これの理由は何でしょうか?そしてそれを修正する方法は?

回答

3066 mario Nov 07 2011 at 00:45

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

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

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

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

  • header / header_remove
  • session_start / session_regenerate_id
  • setcookie / setrawcookie

出力は次のようになります。

  • 意図的ではない:

    • 空白の前<?phpまたは後?>
    • UTF-8バイトオーダーマーク、具体的
    • 以前のエラーメッセージまたは通知
  • 意図的:

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

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

PHPは、第一の出力を受信すると(printecho<html>)それがあろう洗い流す収集されたすべてのヘッダー。その後、必要なすべての出力を送信できます。しかし、それ以上のHTTPヘッダーを送信することは不可能です。

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

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

警告:ヘッダー情報を変更することはできません-ヘッダが既にによって送信された(で開始出力/ WWW / usr2345 / htdocsに/ auth.php:52)は、ライン100上で/www/usr2345/htdocs/index.php

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

括弧内の「出力開始」の注記はより重要です。これは、前の出力のソースを示します。この例では、それはだauth.phpライン52。ここで、時期尚早の出力を探す必要がありました。

典型的な原因:

  1. 印刷、エコー

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

    出力を生成する関数は次のとおりです。

    • printechoprintfvprintf
    • trigger_errorob_flushob_end_flushvar_dumpprint_r
    • readfilepassthruflushimagepngimagejpeg


    とりわけ、ユーザー定義関数。

  2. 生のHTML領域

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

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

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

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

  3. <?php「script.php1行目」の警告の前の空白

    警告が行の出力に言及している場合、1それはほとんどの場合、開始トークンの前の先頭の空白、テキスト、またはHTML<?phpです。

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

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

    ?>
    
    <?php
    

    PHPは、タグを閉じると、実際には1つの改行を消費します。ただし、そのようなギャップにシフトされた複数の改行、タブ、またはスペースは補正されません。

  4. 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
    

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

  5. 後の空白 ?>

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

    特に初心者には、末尾の?>PHPクローズタグを省略することをお勧めします。これにより、これらのケースのごく一部が回避されます。(非常に一般的にinclude()dは、スクリプトが原因です。)

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

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

    • それは時折だgzipストリームのエンコードの設定やob_gzhandler。
    • しかし、それはextension=、暗黙のPHP起動/警告メッセージを生成する二重にロードされたモジュールである可能性もあります。

  7. 先行するエラーメッセージ

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

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

エラーメッセージはありません

を持っているerror_reportingdisplay_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サーバーへのチャンク転送を最小限に抑えることです。

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

  2. 同様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について詳しく説明し、スクリプトを書き直すためのガイドラインをいくつか示します。
203 phihag Nov 07 2011 at 00:44

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

  • 多くの場合、次のようにファイルの最初または最後にある偶発的な空白。

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

       これを回避するには、単にクロージングを省略します?>-とにかく必要ありません。

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

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

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

126 ManishShrivastava Aug 01 2012 at 13:43

私は以前に何度もこのエラーを受け取りました、そして私はすべての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();
?> 

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

90 IpsitaRout Mar 24 2013 at 19:54

以下の行の代わりに

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

それは間違いなくあなたの問題を解決します。同じ問題に直面しましたが、上記の方法でヘッダーの場所を書き込むことで解決しました。

41 SethCarnegie Nov 07 2011 at 00:45

あなたがやる

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

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

34 T.Todua Apr 10 2015 at 02:22

一般的な問題:

(コピー元:ソース)

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

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;
33 Sarfraz Nov 07 2011 at 00:45

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

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

ヘッダーを送信する前に、何も印刷/エコーしないでください。

27 Sliq May 17 2012 at 03:37

簡単なヒント:最初の<?phpタグの直前にあるスクリプト内の単純なスペース(または非表示の特殊文字)がこれを引き起こす可能性があります!特に、チームで作業していて、誰かが「弱い」IDEを使用している場合や、奇妙なテキストエディタでファイルをいじり回している場合は特にそうです。

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

22 MD.SahibBinMahboob Nov 08 2013 at 08:29

別の悪い習慣は、まだ述べられていないこの問題を引き起こす可能性があります。

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

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

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

16 Lupin May 22 2015 at 03:39

DEVプロセスはWINワークステーションおよびLinuxシステム(ホスティング)の両方を持っており、コードの中であなたが関連する行の前に任意の出力が表示されないとき時々 、それはファイルや不足の書式設定することができUnixのLF(改行)行末。

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

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

3 BiswadeepSarkar Feb 03 2015 at 11:50

通常、このエラーは、エコーまたは印刷後にヘッダーを送信するときに発生します。このエラーが特定のページで発生した場合は、を呼び出す前に、ページが何もエコーしていないことを確認してください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()、空白や改行さえも機能させないでください