0

私は、必要に応じてエラー ページを表示するポータブル カスタム エラー ハンドラを作成する初心者です。問題は、ヘッダーまたは html が既に送信されている場合にどうするかです。リダイレクトすることはできず、ブラウザーに既に表示されているものを予測する方法がありません。

良いコードではそれが起こらないことを私は知っています。これは、起こった最悪の出来事に対する最後の手段です。

このコードは、ページに Pray-it-works html ハックを挿入して、ブラウザーにリダイレクトを強制するか、リダイレクトに失敗すると、ページに既に存在するものを非表示にするためにポップアップ表示されるセクションに適切なエラー ページを表示することによって機能します。 .

以下のコードは合理的ですか、ばかげていますか、それとも PHP はより良い解決策を提供しますか? また、それをしっかりさせるためにもっとや​​るべきことはありますか?

<?PHP
// oh crap! something bad happened but...
// yay, my custom error handler caught it.
// It now does some error handler stuff, records the error, sends me a nasty email, etc.
// Decides the error was fatal. Time to display an error page.
// But wait! Alas, what if headers were sent?
// What if a single empty space was already sent to the browser?
// "ominous music".


if (!headers_sent()) {
    // whew! no problem. display a pretty error page.
}else{
    // dammit! somebodies getting fired. 
    // lets see if we can salvage this and show the viewer something nice.

    $mySafeErrorPage = "http://root.com/somePage.html";

    // Step one: Stop as much HTML as possible.
    // Dump anything still in the buffers.
    while (ob_get_level() > 0 && ob_get_status() != false) {
        ob_end_clean();
    }
    // Step two: Make sure our hack isn't stuck inside a comment or script.
    echo'// -- > </script>';

    // Step three: Make sure the safe page exist and is really safe.
    // Insert two redirect hacks. One for JavaScript. The other if script is disabled.
    $headersArray = @get_headers($mySafeErrorPage);
    $headersString = (is_array($headersArray))?implode("\n",$headersArray):$headersArray;
    $validated = (bool)preg_match('#HTTP/.*\s+[(200|301|302)]+\s#i',$headersString);
    if ($validated) {
        echo'
        <script language="javascript" type="text/javascript">
            window.location.href="'.$mySafePage.'"
        </script>
        <meta http-equiv="refresh" content="0; url= '.$mySafeErrorPage.'" />';
    }

    // Step four: 
    // If we're still here, the redirect failed.
    // Display the error page in a giant pop-up block division 
    // to hide anything already sent to browser.
    echo'
    <div style = "z-index:9998;display:block;position:absolute;top:0px;left:0px;height:3000px;width:3000px;background-color:#FFF">
      <div style = "z-index:9999;display:block;position:absolute;top:0px;left:0px;width:300px;height:300px;background-color:#FFF;color:#000">
        MY HTTP 500 MESSAGE
      </div>     
    </div>';
    exit;
}
4

1 に答える 1

1

まず、問題の原因ではなく、結果を修正しようとしています。次に、このコードをどこに配置しますか? ページがレンダリングされる前に? 現時点ではヘッダーが送信されていないため、機能しません。ページがレンダリングされた後?この時点ですべてのヘッダーが送信されるため、機能しません。

このコードのもう 1 つの欠点は、開発者がすべてのページにコードを含めることを覚えておく必要があるという事実です。

「headers already sent」エラーを本当に回避したい場合は、カスタムの my_header() 関数を追加して、PHP の header() をラップし、headers_sent() チェックを行います。そして、他の人が PHP 組み込み関数を使用できないようにします。

my_header の例 (元の header() 関数からコピーされた関数宣言):

function my_header($string, $replace = true, $http_response_code) {
    if(headers_sent()) {
        throw new Exception("Headers were already sent");
    }
    header($string, $replace, $http_response_code);
}

全員が header() の代わりに my_header() を使用しなければならないなど、プロジェクトにいくつかのルールを課すことができます。また、コード レビュー中に、header() を直接呼び出すコードを拒否できます。あなたがプロジェクトの唯一の人なら、物事はより簡単です:)

于 2015-04-05T20:47:57.733 に答える