Register_shutdown_function()を使用してPHPの致命的なエラーを処理する
-
08-10-2019 - |
質問
によると この答えに関するコメント a シャットダウン機能 使用することはできません set_error_handler()
.
ただし、致命的なエラーのためにシャットダウンが発生したかどうかを判断する方法を見つけることができませんでした。
さらに、デバッグバックトレース関数はシャットダウン関数では無効であるように思われるため、致命的なエラーが発生したスタックトレースを記録するにはかなり価値がありません。
だから私の質問は、適切なバックトレースを作成する能力を維持しながら、致命的なエラー(特に未定義の機能呼び出し)で反応する最良の方法は何ですか?
解決
これは私にとってはうまくいきます:
function shutdown() {
$error = error_get_last();
if ($error['type'] === E_ERROR) {
// fatal error has occured
}
}
register_shutdown_function('shutdown');
spl_autoload_register('foo');
// throws a LogicException which is not caught, so triggers a E_ERROR
ただし、おそらくすでにそれを知っていますが、確認するためには、E_ERRORから何らかの形で回復することはできません。
バックトレースに関しては、できません... :(ほとんどの場合、致命的なエラーの場合、特に 未定義関数 エラー、あなたは本当にそれを必要としません。ファイル/行が発生した場所を特定するだけで十分です。その場合、バックトレースは無関係です。
他のヒント
Register_Shutdown_Functionで致命的なエラーと適切なアプリケーションのシャットダウンを区別する1つの方法は、プログラムの最後の行として定数を定義し、次の定義が定義されているかどうかを確認することです。
function fatal_error() {
if ( ! defined(PROGRAM_EXECUTION_SUCCESSFUL)) {
// fatal error has occurred
}
}
register_shutdown_function('fatal_error');
define('PROGRAM_EXECUTION_SUCCESSFUL', true);
プログラムが終了に達した場合、致命的なエラーに遭遇することはできなかったため、定数が定義されている場合は関数を実行しないことがわかります。
ERROR_GET_LAST()は、言及されているように、バックトレースはありませんが、デバッグする必要がある致命的なエラーに関するすべての情報を含む配列です。
一般的に、PHPプログラムが致命的なエラーに遭遇した場合(例外ではなく)、問題を見つけて修正できるようにプログラムを爆破する必要があります。 Register_shutdown_functionは、エラーの報告をオフにしたい生産環境に役立つが、バックグラウンドでエラーをログに記録して応答できるようにしたいと思うことがわかりました。このようなエラーが発生した場合に、関数を使用してユーザーをフレンドリーなHTMLページに誘導して、空白のページを提供するだけではありません。
現在のerror_handlerメソッドを取得するための良いトリック=)
<?php
register_shutdown_function('__fatalHandler');
function __fatalHandler()
{
$error = error_get_last();
//check if it's a core/fatal error, otherwise it's a normal shutdown
if($error !== NULL && $error['type'] === E_ERROR) {
//Bit hackish, but the set_exception_handler will return the old handler
function fakeHandler() { }
$handler = set_exception_handler('fakeHandler');
restore_exception_handler();
if($handler !== null) {
call_user_func($handler, new ErrorException($error['message'], $error['type'], 0, $error['file'], $error['line']));
}
exit;
}
}
?>
また、私はあなたが電話した場合にそれを注意しません
<?php
ini_set('display_errors', false);
?>
PHPがエラーを表示するのを停止します。そうしないと、エラーハンドラーの前にエラーテキストがクライアントに送信されます
これには「ob_start」を使用しています。
function fatal_error_handler($buffer) {
if (preg_match("|(Fatal error:)(.+)|", $buffer, $regs) ) {
//Your code
}
return $buffer;
}
ob_start("fatal_error_handler");