Обрабатывать фатальные ошибки в PHP, используя register_shutdown_function ()
-
08-10-2019 - |
Вопрос
Согласно с Комментарий к этому ответу Можно поймать фатальные ошибки через Функция выключения который не может быть пойман, используя set_error_handler()
.
Тем не менее, я не мог узнать, как определить, произошло ли выключение из-за фатальной ошибки или из-за скрипта, достигающего его конца.
Кроме того, функции Backtrace Debug, кажется, несуществуют в функции отключения, что делает его совершенно бесполезной для регистрации трассировки стека, где произошла фатальная ошибка.
Итак, мой вопрос: какой лучший способ реагировать на фатальные ошибки (особенно неопределенные вызовы функций), сохраняя способность создавать правильный задний результат?
Решение
Это работает для меня:
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 - это определить постоянную в качестве последней строки вашей программы, а затем проверять, определена ли константа:
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");