Подтвердить что ты не робот

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

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

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

4b9b3361

Ответ 1

Да, это возможно. Этот вопрос говорит о более общем вопросе о том, как обрабатывать ошибки в PHP. Вы должны определить и зарегистрировать собственный обработчик ошибок, используя set_error_handler docs, чтобы настроить обработку ошибок 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, эффективно завершая вывод script (если исключение не поймано). Выбросы исключений из ошибок 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
}

Ответ 2

Вы можете глобально настроить это в своем файле php.ini & shy; Docs.

Вы делаете это, указав файл, который будет включен всеми процессами PHP, с директивой auto_prepend_file & shy; Docs:

auto_prepend_file "/full/path/to/a/prepend-file.php"

Выполнение этого внутри глобального файла php.ini гарантирует, что код внутри файла preend всегда будет выведен. Затем вы можете использовать его для регистрации глобального обработчика ошибок, который будет превращать все ошибки в исключения & shy; Docs:

<?php
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
set_error_handler("exception_error_handler");

Этот маленький script превратит все ошибки/предупреждения/уведомления и т.д. в ErrorException.

Объедините его с директивой error_reporting ini & shy; Docs, значения описываются в вашем файле php.ini.

Бросок исключения - очень строгая вещь. Ваши программисты будут вынуждены иметь дело с предупреждениями и ошибками, иначе код не будет работать.

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

Другой альтернативой является регистрация ошибок и предупреждений в файле журнала, а затем мониторинг этого файла с другим процессом и агрегирование информации. Вы можете создать табло с отображением количества предупреждений для каждого приложения и сделать это видимым в офисе, чтобы все видели, насколько хорошо команда работает или что-то вроде этого.

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

Ответ 3

Начиная с 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
);

Ответ 4

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

Ответ 5

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

Тем не менее, мне нужен был способ распечатать сообщение - в моем случае в PHP CLI - так как результат затем анализируется другой программой. Поэтому я не хотел печатать сообщение каким-то образом, но точно так же, как это обычно делает PHP. Я просто хотел остановить процесс CLI PHP с кодом выхода != 0 сразу после того, как было опубликовано уведомление/предупреждение, и ничего не меняйте.

К сожалению, по-видимому, не существует способа выхода из script по умолчанию, не изменяя всю обработку ошибок. Поэтому мне нужно было переопределить обработчик ошибок по умолчанию (который реализован на 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 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
);

Ответ 6

Вы можете включить error_reporting в E_ALL в файле конфигурации PHP вашего сервера.

В PHP 5 доступен новый уровень ошибки E_STRICT. Поскольку E_STRICT не включен в E_ALL, вы должны явно включить такой уровень ошибок. Включение E_STRICT во время разработки имеет определенные преимущества. Сообщения STRICT помогут вам использовать последний и самый рекомендуемый метод кодирования, например, предупреждают вас об использовании устаревших функций.

Ссылка: Руководство по настройке PHP

Следующие настройки позволяют вам выводить все ошибки в script. Обратите внимание, что они должны быть включены в начало всех ваших файлов script.

<?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);

?>