Возможно ли, чтобы PHP прекратил выполнение по уведомлению / предупреждению во всем мире?
Мы запускаем сервер разработки с большим количеством сайтов, но хотим заставить наших разработчиков исправлять эти предупреждения / уведомления (или обращаться за помощью к ним как минимум), а не игнорировать и перемещаться дальше.
Да, это возможно. Этот вопрос говорит о более общем вопросе о том, как обрабатывать ошибки в PHP. Вы должны определить и зарегистрировать собственный обработчик ошибок с помощью set_error_handler
для настройки обработки ошибок PHP.
ИМХО лучше всего выбросить исключение из любой ошибки PHP и использовать блоки try / catch для управления потоком программы, но мнения по этому вопросу различаются.
Для достижения поставленной цели OP вы можете сделать что-то вроде:
function errHandle($errNo, $errStr, $errFile, $errLine) { $msg = "$errStr in $errFile on line $errLine"; if ($errNo == E_NOTICE || $errNo == E_WARNING) { throw new ErrorException($msg, $errNo); } else { echo $msg; } } set_error_handler('errHandle');
Вышеприведенный код генерирует ErrorException
любое время, когда возникает E_NOTICE
или E_WARNING
, эффективно завершая вывод сценария (если исключение не поймано). Бросание исключений из ошибок PHP лучше всего сочетается с параллельной стратегией обработки исключений ( set_exception_handler
), чтобы изящно прекратить работу в производственных средах.
Обратите внимание, что приведенный выше пример не будет относиться к оператору подавления ошибок @
. Если это важно для вас, просто добавьте проверку с функцией error_reporting()
как показано здесь:
function errHandle($errNo, $errStr, $errFile, $errLine) { if (error_reporting() == 0) { // @ suppression used, don't worry about it return; } // handle error here }
Вы можете глобально настроить это в своих файлах файлов php.ini .
Вы делаете это, указав файл, который включается всеми процессами PHP с директивой auto_prepend_file
Документы :
auto_prepend_file "/full/path/to/a/prepend-file.php"
Выполнение этого внутри глобального файла php.ini гарантирует, что код внутри файла preend всегда будет выведен. Затем вы можете использовать его для регистрации глобального обработчика ошибок, который превратит все ошибки в исключения. Документы :
<?php function exception_error_handler($errno, $errstr, $errfile, $errline ) { throw new ErrorException($errstr, 0, $errno, $errfile, $errline); } set_error_handler("exception_error_handler");
Этот маленький скрипт превратит все ошибки / предупреждения / уведомления и т. Д. В ErrorException
.
Объедините его с директивой docs error_reporting
ini , значения описываются в файле php.ini.
Выбрасывание исключения – очень строгая вещь. Ваши программисты будут вынуждены иметь дело с предупреждениями и ошибками, иначе код не будет работать.
Наверное, это слишком много для ваших программистов, а не социально приемлемых в вашей компании. Вместо этого вы также можете регистрировать все ошибки и добавлять их в конце вывода (или вверху, чтобы он был более заметным), используя буферизацию вывода.
Другой альтернативой является регистрация ошибок и предупреждений в файле журнала, а затем мониторинг этого файла с другим процессом и агрегирование информации. Вы можете создать табло с отображением количества предупреждений для каждого приложения и сделать это видимым в офисе, чтобы все видели, насколько хорошо команда работает или что-то вроде этого.
Я пытаюсь сказать следующее: рядом с технической проблемой, это социальная проблема, с которой вам нужно проявлять творческий подход и на самом деле говорить о проблеме со своими разработчиками. Вам нужно четко указать, почему важно исправлять предупреждения и ошибки, а также то, как их кодирование и навыки выиграют от этого.
Начиная с PHP 5.3.0:
set_error_handler( function(int $nSeverity, string $strMessage, string $strFilePath, int $nLineNumber){ if(error_reporting()!==0) // Not error suppression operator @ throw new \ErrorException($strMessage, /*nExceptionCode*/ 0, $nSeverity, $strFilePath, $nLineNumber); }, /*E_ALL*/ -1 );
Если вы находитесь в среде разработки, вы можете рассмотреть возможность установки модуля Xdebug и установить xdebug.halt_level=E_WARNING|E_NOTICE|E_USER_WARNING|E_USER_NOTICE
где-то в ваших PHP-файлах ini. Разработчик может сбросить xdebug.halt_level
, но мы имеем ту же проблему с ответом на основе set_error_handler
, потому что мы можем восстановить обработчик до его исходного значения.
Другие решения реализуют собственный обработчик ошибок, который переопределяет механизм регистрации ошибок по умолчанию. Это означает, что когда мы устанавливаем собственный обработчик ошибок, уведомление / предупреждение больше не печатается по умолчанию, поэтому мы меняем больше, чем просто «прекратить выполнение скрипта при уведомлении / предупреждении».
Тем не менее, мне нужен был способ распечатать сообщение – в моем случае в PHP CLI – так как результат затем анализируется другой программой. Поэтому я не хотел печатать сообщение каким-то образом, но точно так же, как это обычно делает PHP. Я просто хотел остановить процесс CLI PHP с кодом выхода != 0
сразу после того, как было опубликовано уведомление / предупреждение и ничего не изменило .
К сожалению, по-видимому, не существует способа выхода из сценария по умолчанию, не изменяя всю обработку ошибок . Поэтому мне нужно было переопределить обработчик ошибок по умолчанию (который реализован на C) в PHP.
Для этого я рассмотрел механизм печати ошибок по умолчанию в исходном коде PHP и портировал соответствующие фрагменты из C в PHP, чтобы получить следующий обработчик ошибок, который я хочу поделиться с вами, если вам нужно что-то похожее:
set_error_handler( function($errNo, $errStr, $errFile, $errLine) { $error_type_str = 'Error'; // Source of the switch logic: default error handler in PHP's main.c switch ($errNo) { case E_ERROR: case E_CORE_ERROR: case E_COMPILE_ERROR: case E_USER_ERROR: $error_type_str = "Fatal error"; break; case E_RECOVERABLE_ERROR: $error_type_str = "Recoverable fatal error"; break; case E_WARNING: case E_CORE_WARNING: case E_COMPILE_WARNING: case E_USER_WARNING: $error_type_str = "Warning"; break; case E_PARSE: $error_type_str = "Parse error"; break; case E_NOTICE: case E_USER_NOTICE: $error_type_str = "Notice"; break; case E_STRICT: $error_type_str = "Strict Standards"; break; case E_DEPRECATED: case E_USER_DEPRECATED: $error_type_str = "Deprecated"; break; default: $error_type_str = "Unknown error"; break; } fwrite(STDERR, "PHP $error_type_str: $errStr in $errFile on line $errLine\n"); exit(1); }, E_ALL );
Вы можете включить error_reporting в E_ALL в файле конфигурации PHP вашего сервера.
В PHP 5 доступен новый уровень ошибок E_STRICT. Поскольку E_STRICT не включен в E_ALL, вы должны явно включить такой уровень ошибок. Включение E_STRICT во время разработки имеет определенные преимущества. Сообщения STRICT помогут вам использовать последний и самый рекомендуемый метод кодирования, например, предупреждают вас об использовании устаревших функций.
Ссылка: Руководство по настройке PHP
Следующие настройки позволяют вам выводить все ошибки в скрипте. Обратите внимание, что они должны быть включены в начало всех ваших файлов сценариев.
<?php // Turn off all error reporting error_reporting(0); // Report simple running errors error_reporting(E_ERROR | E_WARNING | E_PARSE); // Reporting E_NOTICE can be good too (to report uninitialized // variables or catch variable name misspellings ...) error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE); // Report all errors except E_NOTICE // This is the default value set in php.ini error_reporting(E_ALL ^ E_NOTICE); // Report all PHP errors (see changelog) error_reporting(E_ALL); // Report all PHP errors error_reporting(-1); // Same as error_reporting(E_ALL); ini_set('error_reporting', E_ALL); ?>