web-dev-qa-db-ja.com

致命的な例外が発生したときに500を返すようにphpを取得するにはどうすればよいですか?

PHPの致命的なエラーは、ステータスコード200としてHTTPクライアントに返されます。ステータスコード500(内部サーバーエラー)を返すようにするにはどうすればよいですか?

50
Mike
header("HTTP/1.1 500 Internal Server Error");
50

これはまさに昨日私が抱えていた問題であり、次のような解決策を見つけました。

1)まず、PHP致命的なエラー、エラータイプE_ERRORです。このエラーが発生すると、スクリプトにエラーが保存され、実行が終了します。保存されたエラーを取得できます。関数error_get_last()を呼び出すことにより。

2)スクリプトが終了する前に、コールバック関数register_shutdown_function()が常に呼び出されます。そのため、この関数でエラーハンドラを登録して、必要な処理を行う必要があります。この場合、ヘッダー500とカスタマイズされた内部エラーページ(オプション)を返します。

function my_error_handler()
{
  $last_error = error_get_last();
  if ($last_error && $last_error['type']==E_ERROR)
      {
        header("HTTP/1.1 500 Internal Server Error");
        echo '...';//html for 500 page
      }
}
register_shutdown_function('my_error_handler');

注:E_USER *で始まるカスタムエラータイプをキャッチする場合、関数set_error_handler()を使用してエラーハンドラーを登録し、関数trigger_errorでエラーをトリガーできますが、このエラーハンドラーはE_ERRORエラータイプを処理できません。 エラーハンドラ に関するphp.netの説明を参照してください

23
fuyi

「set_exception_handler」を使用して、キャッチされなかった例外を処理しました。

function handleException($ex) {
      error_log("Uncaught exception class=" . get_class($ex) . " message=" . $ex->getMessage() . " line=" . $ex->getLine());
      ob_end_clean(); # try to purge content sent so far
      header('HTTP/1.1 500 Internal Server Error');
      echo 'Internal error';
    }

set_exception_handler('handleException');
6
Matti Haavikko

PHP E_ERRORは、PHP documentation: http://www.php.net/manual /en/function.set-error-handler.php

そのリンクに従って「E_PARSE、E_CORE_ERROR、E_CORE_WARNING、E_COMPILE_ERROR、E_COMPILE_WARNING、およびほとんどのE_STRICT」を処理することもできません。

E_USER_ERRORを含む他のエラー、警告、および通知にハンドラーを提供できますが、このエラーはtrigger_error()を使用してプログラマーによって意図的にスローされるだけなので、実際にはそれほど便利ではありません。

そしてもちろん、どんな例外もキャッチできます(ネイティブのPHP関数)によってスローされた例外も)。

これは問題だと思います。サーバーは、アプリケーションコードがクラッシュして焼き付いたときに200 OKを返すべきではありません。

3
Jonathan Hanson

標準PHP configuration doesエラーが発生したときに500を返します!display_errors = offであることを確認してください。

ini_set('display_errors', 0); 
noFunction();

本番環境では、display_errorsディレクティブはデフォルトでオフになっています。

3
lukyer

致命的なエラー(セミコロンの欠落などのコンパイルエラー)を処理する際に難しいのは、スクリプトが実行されないことです。そのため、そのスクリプトにステータスコードを設定することは役に立ちません。ただし、スクリプトを含めるか必要とする場合、含まれるスクリプトのエラーに関係なく、呼び出し元のスクリプトが実行されます。これで、私はこのソリューションに来ます:

rock-solid-script.php:

// minimize changes to this script to keep it rock-solid
http_response_code(500); // PHP >= 5.4
require_once("script-i-want-to-guard-for-errors.php");

script-i-want-to-guard-for-errors.php:

// do all the processsing
// don't produce any output
// you might want to use output buffering

http_response_code(200); // PHP >= 5.4

// here you can produce the output

呼び出しをrock-solid-script.phpに転送すれば、準備は完了です。

.htaccessでデフォルトのステータスコードを500に設定した方がいいと思います。それは私にはもっとエレガントに思えますが、私はそれをやってのける方法を見つけることができません。 RewriteRule R-flagを試しましたが、これによりphpの実行が完全に妨げられるため、それは役に立ちません。

1
Remco Nijhuis

PHPエラー処理を使用できます

http://www.w3schools.com/php/php_error.asp

0
Xinus

header("HTTP/1.1 200 OK", true, 200);を実行パスの最後の行として設定することを忘れないでください:

_//first things first:
header("HTTP/1.1 500 Internal Server Error", true, 500);


//Application code, includes, requires, etc. [...]


//somewhere something happens
//die();
throw new Exception("Uncaught exception!");


//last things last, only reached if code execution was not stopped by uncaught exception or some fatal error
header("HTTP/1.1 200 OK", true, 200);
_

_PHP 5.4_では、上記のheader関数をはるかに優れた http_response_code(200) または http_response_code(500)

0

try/catch を使用してスローされたエラーをキャッチし、そのキャッチブロックを使用して、500エラーで header() を送信する必要があります。

_try {
    ...badcode...
    throw new Exception('error');

} catch (Exception $e) {

    header("Status: 500 Server Error");
    var_dump($e->getMessage());
}
_

致命的な例外がtry {} catchブロックに囲まれていない場合、グローバルハンドラーを登録し、register_shutdown_function()を使用してスクリプト終了時にエラーをチェックする必要があります。

0
Xeoncross