Согласно комментарию к этому ответу, можно поймать Fatal Errors через функцию выключения, которую невозможно поймать с помощью set_error_handler()
.
Тем не менее, я не мог узнать, как определить, произошло ли завершение из-за фатальной ошибки или из-за того, что скрипт достиг своего конца.
Кроме того, функции отладки backgrace, по-видимому, не работают в функции выключения, что делает его довольно бесполезным для регистрации трассировки стека, где произошла Fatal Error.
Поэтому мой вопрос: какой лучший способ реагировать на Fatal Errors (особенно неопределенные вызовы функций), сохраняя при этом способность создавать правильную обратную линию?
Это работает для меня:
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.
Что касается backtrace, вы не можете … 🙁 В большинстве случаев фатальной ошибки, особенно ошибок Undefined , вам это действительно не нужно. Точное определение файла / строки, где она происходила, является достаточной. в таком случае.
Один из способов отличить фатальную ошибку и правильное закрытие приложения с помощью функции register_shutdown_function – определить константу в качестве последней строки вашей программы, а затем проверить, определена ли константа:
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");