0

Остановить выполнение скрипта при возникновении уведомления/предупреждения

9

Возможно ли глобально остановить выполнение PHP при возникновении уведомления / предупреждения?

У нас есть сервер разработки с множеством сайтов, и мы хотим заставить наших разработчиков исправлять эти предупреждения и уведомления (или хотя бы просить о помощи в их решении), вместо того чтобы игнорировать их и продолжать писать код.

4 ответ(ов)

0

С начала версии 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, передавая в него информацию об ошибке, такую как сообщение, уровень серьезности, файл и номер строки, где произошла ошибка.

Используя этот подход, вы можете централизовать обработку ошибок в вашем приложении, что упрощает отладку и ведение журналов.

0

Если вы находитесь в среде разработки, возможно, стоит рассмотреть установку модуля Xdebug и задать параметр xdebug.halt_level=E_WARNING|E_NOTICE|E_USER_WARNING|E_USER_NOTICE в одном из ваших файлов конфигурации PHP (php.ini). Разработчик может сбросить xdebug.halt_level, но с ответом, основанным на set_error_handler, мы сталкиваемся с аналогичной проблемой, поскольку обработчик можно восстановить до его исходного значения.

0

Другие решения реализуют пользовательский обработчик ошибок, который переопределяет механизм журналирования ошибок по умолчанию. Это означает, что когда мы устанавливаем пользовательский обработчик ошибок, уведомления/предупреждения больше не выводятся в стандартном формате, и мы изменяем больше, чем просто "остановку выполнения скрипта при уведомлении/предупреждении".

Однако мне был нужен способ вывести сообщение — в моем случае в 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
);
0

Обратите внимание на значение, возвращаемое функцией 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() в пользовательских обработчиках.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь