Я должен что-то упустить в моем понимании обработки ошибок PHP, в частности, подавления их вывода. Когда происходит фатальная ошибка, я ожидаю, что моя функция обработчика выключения корректно обработает ее и завершит выполнение скрипта. Это работает, как ожидалось. Однако я не могу запретить PHP выводить информацию о фатальной ошибке.
Мой файл php.ini содержит следующие директивы:
error_reporting = E_ALL | E_STRICT
display_errors = Off
Я установил error_reporting
, чтобы сообщать обо всем, и я использую специальный обработчик ошибок, чтобы генерировать исключения. Я ожидаю, что display_errors = Off
предотвратит отображение ЛЮБЫХ сообщений об ошибках.
В любом случае, когда возникает фатальная ошибка, пользовательский обработчик ошибок игнорируется (поскольку выполнение скрипта немедленно останавливается) и выполняется обработчик завершения работы.
Теперь перейдем к моему упрощенному коду:
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 'Off');
function shutdown_handler()
{
$err = error_get_last();
$fatal = array(E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR);
if ($err && in_array($err['type'], $fatal)) {
echo "\n\ntest fatal error output\n\n";
}
exit();
}
register_shutdown_function('shutdown_handler');
Чтобы проверить его, я генерирую фатальную ошибку «Допустимый размер памяти исчерпан», например:
// max out available memory
$data = '';
while(true) {
$data .= str_repeat('#', PHP_INT_MAX);
}
Поскольку у меня display_errors = Off
, я ожидаю, что это будет выдает только следующий вывод (согласно обработчику выключения):
test fatal error output
Но вместо этого я продолжаю получать:
PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 2147483648 bytes) in /home/daniel/mydev/php/test0.php on line 24
PHP Stack trace:
PHP 1. {main}() /home/daniel/mydev/php/test0.php:0
PHP 2. str_repeat() /home/daniel/mydev/php/test0.php:24
test fatal error output
Что мне не хватает, что предотвратит вывод этой трассировки ошибки?
ЗАКЛЮЧЕНИЕ
Похоже, как @Cthos мудро заметил, что «E_ERROR и display_errors несовместимы друг с другом."
Это также относится к E_PARSE (и я предполагаю, что E_CORE_ERROR / E_COMPILE_ERROR, но я не нарушал мою установку PHP, чтобы проверить ее). Я полагаю, имеет смысл, что PHP в этих случаях принудительно запускает трассировку ошибки в STDOUT потому что, если бы это было не так, вы никогда не узнаете, что / почему что-то пошло не так.
Итак, решение в этом случае было бы:
error_reporting = (E_ALL & ~ E_ERROR)
или во время выполнения с использованием error_reporting (E_ALL & ~ E_ERROR);
Что касается других фатальных ошибок, таких как E_PARSE, E_CORE_ERROR и т. Д., Вам просто нужно убедиться, что ваш код правильный и что ваш PHP работает. Если вы попытаетесь заглушить ошибки E_PARSE и обработать их в своей функции выключения, это не сработает. потому что ошибки синтаксического анализа не позволяют PHP зайти так далеко.
Итак, обновленный / рабочий обработчик завершения работы выглядит вроде этого:
error_reporting(E_ALL & ~ E_ERROR);
function shutdown_handler()
{
$err = error_get_last();
if ($err && $err['type'] == E_ERROR) {
$msg = 'PHP Fatal Error: '.$err['message'].' in '.$err['file'].
' on line '.$err['line'];
echo $msg, PHP_EOL;
}
exit();
}