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


831

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

警告:ヘッダー情報を変更できません-23 / 行の/some/file.php で(/some/file.php:12で開始された出力)によって既に送信されたヘッダー

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

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



テキストが出力されない(ことを確認してくださいob_startob_end_clean() 、ここで有用であろう)。次に、Cookieまたはセッションをに設定しob_get_contents()、それを使用ob_end_clean()してバッファをクリアします。
Jack Tuck 14

safeRedirect私のPHPライブラリの関数を使用してください:github.com/heinkasner/PHP-Library/blob/master/extra.php
heinkasner

5
~~~~~~~~~~ファイルのUTF-8UTF-8 (Without BOM)
エンコードは

回答:


2997

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

出力を行う前に、 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>

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

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

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

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

警告:ヘッダー情報を変更できません-ヘッダーは既に送信されており (出力は / www / usr2345 / htdocs / auth.php:52 から開始されます)/www/usr2345/htdocs/index.phpの100行目

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

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

典型的な原因:

  1. 印刷、エコー

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

    出力を生成する関数には、

    • printechoprintfvprintf
    • trigger_errorob_flushob_end_flushvar_dumpprint_r
    • readfilepassthruflushimagepngimagejpeg


    特にユーザー定義関数。

  2. 生のHTML領域

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

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

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

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

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

    警告が行内の出力を参照している場合、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標準で義務付けられています)。ただし、ほとんどのプログラマーおよびコンソールエディターは次のことを行います。

    UTF-8 BOMプレースホルダーを示すjoesエディター、およびMCエディターにドット

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

    utf-8 bomを示すbeav hexeditor

    簡単な修正は、ファイルを「UTF-8(BOMなし)」または同様の命名法で保存するようにテキストエディターを設定することです。それ以外の場合は、新しいファイルを作成して、以前のコードをコピー&ペーストするだけで済むことがよくあります。

    修正ユーティリティ

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

    phptags  --whitespace  *.php

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

  5. 後の空白 ?>

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

    一般に、特に初心者には、末尾の?>PHP終了タグを省略してください。これは、これらのケースのごく一部を避けています。(かなり一般的にinclude()dスクリプトが原因です。)

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

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

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

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

  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設定などにも依存します。)

さらなるリンク


また、通常のnotepad.exeはトリッキーです。私は通常、ファイルがエンコードされていても、BOMを追加しないNetBeansを使用しています。後でメモ帳でファイルを編集すると、特にIISがWebサーバーである場合に、処理が失敗します。Apacheが(意図的に追加された)BOMを破棄するようです。
Teson、2015

4
?>phpファイルの最後から閉じることを削除することは、通常、これらのエラーを最小限に抑えるのに役立つ良い方法です。ファイルの最後に不要な空白が発生することはなく、後で応答にヘッダーを追加することもできます。また、出力バッファリングを使用していて、インクルードされたファイルによって生成された部分の最後に不要な空白が追加されたくない場合にも便利です。
Nikita

奇妙なことに、cPanel Linux HostingからVPSにファイルを移動しました。それが正しく機能する前に、ここでこのエラーが表示されました(ヘッダーの前にhtmlコードがありました)。どうして?
Pablo Escobar 2017

@Purushotamrawat「しかし、それは他のサーバーで動作しました!」という部分を読みましたか
マリオ

1
@PeterSMcIntyre UTF8 BOMはおそらく(それを修正)/出力バッファリングが有効になっていません(それに依存しないでください)。
マリオ2017

199

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

  • 多くの場合、次のように、ファイルの最初または最後に偶然の空白文字があります。

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

       これを回避するには、単に締めくくりを省略します?>-とにかく必要ではありません。

  • phpファイルの先頭にあるバイトオーダーマーク。16進エディタを使用してphpファイルを調べ、そうであるかどうかを確認します。それらはバイトで始まる必要があります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本文を出力する理由を実際に判断する必要があります。これは、電話をかけて、電話番号が間違っていることを発信者に伝える前に、1日と天気について話し合うようなものです。


おかげで助けてくれます
Vishwa Pratap

122

私は以前にこのエラーを何度も受けましたが、すべてのPHPプログラマがこのエラーを少なくとも1回は受けたことは確かです。

可能な解決策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();
?> 

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


18
ob_start()問題を隠すだけです。この特定の問題を解決するために使用しないでください。
ジャック

@ジャック私が使用していない場合はob_start()、その後、私はこの問題を解決するために何をすべき:Headers already sent
Shafizadeh

@Sajad使用しているエディターが原因でエラーが発生する場合は、設定をいじって問題の原因を停止するか、エディターを切り替えてください。その他の理由でエラーが発生した場合は、この質問の回答(特に承認された回答)を読んで、問題が実際に何であるかを理解し、解決してください。
Samsquanch 2015

3
ob_start()問題を「隠す」のではなく、問題を解決します。
TMS

1
サーバーにファイルをアップロードするときに、PHP5.3もサポートするPHP 5.6以上のサーバーを使用すると、このような問題が発生しました
GGSoft

86

以下の行の代わりに

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

あなたがやる

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

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


32

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

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

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


31

よくある問題:

(コピーソース

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

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)上記のいずれも役に立たない場合は、JAVASCRIPTリダイレクトを使用します(ただし、強く非推奨の方法)。これは、カスタムケースでの最後のチャンスかもしれません...:

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

明示的に設定301または302重要なのはなぜですか?
ジャニスElmeris

26

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

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


22

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

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

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

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


2
いくつかの標準(Zendなど)によると、?>どのような場合でもファイルに終了タグを配置しないでください
Daniel W.

これをWindows環境で再現することはできません。任意の組み合わせ(終了タグ、ブランクの追加、Enterキーの押下など)を使用して機能するためです。この問題は主にLinux環境で発生するようです。
JuniorMayhéJun

@JuniorM再現可能である必要があります。要点などで実験していたコードを共有できますか?
MD。サヒブビンマブーブ2015年

最新のWampがインストールされたWindows 7を使用しています。このバグは行末の隠し文字に関係していると思います。Wordpressのshortcodes.phpが問題の原因でした。このファイルに簡単な関数を追加すると、この「ヘッダー送信」エラーが発生し始めました。私のshortcodes.phpをwordpress 'と比較しましたが、CR LF(通常のWindowsの行末)を除いて、問題ありませんでした。LF(Linuxの行末)の代わりにWordpressリポジトリから元のファイルをダウンロードして解決しCR LF、関数をテーマのfunctions.phpに移動しました。ベース:bit.ly/1Gh6mzN
ジュニアMayhéJun

@Sahib、まだ私がこの回答で述べられていることを再現できないことに注意してください。Linux環境では、答えはまったく問題ありません。私はの間の空白のようなものをテストし?> <?php、単一の空白行を削除して追加し、終了タグを追加して省略しました?>。Windows + Wampでは、これらすべての組み合わせが正常に機能します。
Wierd

15

開発プロセスにWINワークステーションとLINUXシステム(ホスティング)の両方があり、コードで関連する行の前に出力が表示されない場合、ファイルのフォーマットとUnix LF(ラインフィード)の欠如である場合があります。 行末。

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

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


2

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.