Остановить выполнение скрипта при возникновении уведомления/предупреждения
Возможно ли глобально остановить выполнение PHP при возникновении уведомления / предупреждения?
У нас есть сервер разработки с множеством сайтов, и мы хотим заставить наших разработчиков исправлять эти предупреждения и уведомления (или хотя бы просить о помощи в их решении), вместо того чтобы игнорировать их и продолжать писать код.
4 ответ(ов)
С начала версии PHP 5.3.0 вы можете использовать функцию set_error_handler
для перехвата ошибок и их обработки. Пример кода выглядит следующим образом:
set_error_handler(
function(int $nSeverity, string $strMessage, string $strFilePath, int $nLineNumber){
if(error_reporting() !== 0) // Запрос на проверку отключения ошибок с помощью оператора @
throw new \ErrorException($strMessage, /*nExceptionCode*/ 0, $nSeverity, $strFilePath, $nLineNumber);
},
/*E_ALL*/ -1
);
Здесь мы определяем анонимную функцию, которая будет вызываться при возникновении ошибки. Внутри функции мы проверяем, не отключены ли сообщения об ошибках с помощью оператора подавления @
. Если ошибки не подавлены, мы выбрасываем исключение ErrorException
, передавая в него информацию об ошибке, такую как сообщение, уровень серьезности, файл и номер строки, где произошла ошибка.
Используя этот подход, вы можете централизовать обработку ошибок в вашем приложении, что упрощает отладку и ведение журналов.
Если вы находитесь в среде разработки, возможно, стоит рассмотреть установку модуля Xdebug и задать параметр xdebug.halt_level=E_WARNING|E_NOTICE|E_USER_WARNING|E_USER_NOTICE
в одном из ваших файлов конфигурации PHP (php.ini). Разработчик может сбросить xdebug.halt_level
, но с ответом, основанным на set_error_handler
, мы сталкиваемся с аналогичной проблемой, поскольку обработчик можно восстановить до его исходного значения.
Другие решения реализуют пользовательский обработчик ошибок, который переопределяет механизм журналирования ошибок по умолчанию. Это означает, что когда мы устанавливаем пользовательский обработчик ошибок, уведомления/предупреждения больше не выводятся в стандартном формате, и мы изменяем больше, чем просто "остановку выполнения скрипта при уведомлении/предупреждении".
Однако мне был нужен способ вывести сообщение — в моем случае в PHP CLI — поскольку вывод затем парсится другой программой. Я не хотел выводить сообщение каким-то образом, а именно так, как это обычно делает PHP. Я просто хотел остановить процесс PHP CLI с кодом выхода != 0
сразу после того, как уведомление/предупреждение будет выведено, и ничего больше не менять.
К сожалению, не существует стандартного способа завершения скрипта без изменения всей обработки ошибок. Поэтому мне пришлось заново реализовать обработчик ошибок по умолчанию (который реализован на C) на PHP.
Для этого я изучил механизм вывода ошибок по умолчанию в исходном коде PHP и портировал соответствующие части из C в PHP, чтобы получить следующий обработчик ошибок, который я хочу поделиться с вами на случай, если вам нужно что-то подобное:
set_error_handler(
function($errNo, $errStr, $errFile, $errLine) {
$error_type_str = 'Error';
// Источник логики switch: обработчик ошибок по умолчанию в main.c PHP
switch ($errNo) {
case E_ERROR:
case E_CORE_ERROR:
case E_COMPILE_ERROR:
case E_USER_ERROR:
$error_type_str = "Фатальная ошибка";
break;
case E_RECOVERABLE_ERROR:
$error_type_str = "Восстанавливаемая фатальная ошибка";
break;
case E_WARNING:
case E_CORE_WARNING:
case E_COMPILE_WARNING:
case E_USER_WARNING:
$error_type_str = "Предупреждение";
break;
case E_PARSE:
$error_type_str = "Ошибка синтаксиса";
break;
case E_NOTICE:
case E_USER_NOTICE:
$error_type_str = "Уведомление";
break;
case E_STRICT:
$error_type_str = "Строгие стандарты";
break;
case E_DEPRECATED:
case E_USER_DEPRECATED:
$error_type_str = "Устаревший";
break;
default:
$error_type_str = "Неизвестная ошибка";
break;
}
fwrite(STDERR, "PHP $error_type_str: $errStr в $errFile на строке $errLine\n");
exit(1);
},
E_ALL
);
Обратите внимание на значение, возвращаемое функцией error_reporting() при использовании оператора @:
До версии PHP 8.0.0 вызов error_reporting() внутри пользовательского обработчика ошибок всегда возвращал 0, если ошибка была подавлена с помощью оператора @. Начиная с PHP 8.0.0, функция возвращает значение E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR | E_PARSE.
Это изменение может повлиять на обработку ошибок в вашем коде, если вы полагаетесь на значение, возвращаемое error_reporting() в пользовательских обработчиках.
Функции startsWith() и endsWith() в PHP
Как получить расширение файла в PHP?
Как читать большой файл построчно?
ReCaptcha 2.0 с использованием AJAX
Почему нельзя вызывать абстрактные функции из абстрактных классов в PHP?