set_error_handler не работает, как я хочу, чтобы это работало - PullRequest
11 голосов
/ 31 августа 2008

Я совершаю прыжок: мои PHP-скрипты ВСЕ будут терпеть неудачу изящно!

По крайней мере, это то, на что я надеюсь ... `

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

Я проверяю это на странице практики:

function customError($level,$message,$file,$line,$context) {
    echo "Sorry, an error has occured on line $line.<br />";
    echo "The function that caused the error says $message.<br />";
    die();
}

set_error_handler("customError");

echo($imAFakeVariable);

Это работает нормально, возвращая:

Извините, в строке 17 произошла ошибка. Функция, которая вызвала ошибка говорит о неопределенной переменной: imAFakeVariable.

Однако эта настройка не работает для неопределенных функций.

function customError($level,$message,$file,$line,$context) {
    echo "Sorry, an error has occured on line $line.<br />";
    echo "The function that caused the error says $message.<br />";
    die();
}

set_error_handler("customError");

imAFakeFunction();

Возвращает:

Неустранимая ошибка: вызов неопределенной функции: imafakefunction () in /Library/WebServer/Documents/experimental/errorhandle.php в строке 17

Почему мой пользовательский обработчик ошибок не перехватывает неопределенные функции? Есть ли другие проблемы, которые это вызовет?

Ответы [ 6 ]

11 голосов
/ 31 августа 2008

set_error_handler предназначен для обработки ошибок с кодами: E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE. Это связано с тем, что set_error_handler предназначен для сообщения об ошибках, выданных пользователем функцией ошибок trigger_error.

Однако я нашел этот комментарий в руководстве, который может вам помочь:

"Следующие типы ошибок не могут быть обработаны с помощью определенной пользователем функции: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING и большая часть E_STRICT, возникающих в файл, где set_error_handler() называется. "

Это не совсем так. set_error_handler() не может справиться с ними, но ob_start() может обработать как минимум E_ERROR.

<?php

function error_handler($output)
{
    $error = error_get_last();
    $output = "";
    foreach ($error as $info => $string)
        $output .= "{$info}: {$string}\n";
    return $output;
}

ob_start('error_handler');

will_this_undefined_function_raise_an_error();

?>

Действительно, хотя об этих ошибках, например, следует сообщать в файле без вывода сообщений. Надеюсь, у вас не будет много E_PARSE ошибок в вашем проекте! : -)

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

6 голосов
/ 29 марта 2011

Я думаю, вам нужно использовать register_shutdown_function также

Например:

 register_shutdown_function( array( $this, 'customError' ));.

   function customError() 
   {

     $arrStrErrorInfo = error_get_last();

     print_r( $arrStrErrorInfo );

   }
2 голосов
/ 31 августа 2008

Из документации (выделение добавлено):

Следующие типы ошибок не могут быть обработаны с помощью определяемой пользователем функции: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING, и большая часть E_STRICT вызывается в файле, где (*) вызывается в файле, где (*) вызывается (где) вызывается * в том случае, когда файл * вызывается в этом файле (где * вызывается) в том месте, где * вызывается * в том случае, когда файл * вызывается в этом файле (где * вызывается), где (*) вызывается в этом файле, где (*) вызывается в качестве файла, где (*) вызывается в этом файле, где (если это вызвано), то файл (*) вызывается в этом файле, где (*) вызывается в этом файле, где (*) вызывается в этом файле (где__обозреватель_) вызывается в этом файле (где * указывается в файле). 1008 *

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

PS, если вы используете свой собственный обработчик ошибок, вам следует позаботиться о том, чтобы правильно обрабатывать оператор @. Из документации (выделение добавлено):

Важно помнить, что стандартный обработчик ошибок PHP полностью обойден. Настройки error_reporting () не окажут никакого влияния, и ваш обработчик ошибок будет вызван независимо - однако вы все равно можете прочитать текущее значение error_reporting и действовать соответствующим образом. Особо следует отметить, что это значение будет равно 0, если оператор, вызвавший ошибку, был добавлен оператором @ error-control.

1 голос
/ 31 августа 2008

Почему мой пользовательский обработчик ошибок не перехватывает неопределенные функции? Есть ли другие проблемы, которые это вызовет?

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

Если вы хотите, чтобы ваши скрипты корректно проваливались при написании в стиле PHP, попробуйте поместить всю страницу в функцию, а затем вызвать ее в блоке try..catch.

0 голосов
/ 13 марта 2015

Я какое-то время играл с обработкой ошибок, и похоже, что она работает по большей части.

function fatalHandler() {
    global $fatalHandlerError, $fatalHandlerTitle;

    $fatalHandlerError = error_get_last();

    if( $fatalHandlerError !== null ) {

        print($fatalHandlerTitle="{$fatalHandlerTitle} | ".join(" | ", $fatalHandlerError).
                (preg_match("/memory/i", $fatalHandlerError["message"]) ? " | Mem: limit ".ini_get('memory_limit')." / peak ".round(memory_get_peak_usage(true)/(1024*1024))."M" : "")."\n".
                        "GET: ".var_export($_GET,1)."\n".
                        "POST: ".var_export($_POST,1)."\n".
                        "SESSION: ".var_export($_SESSION,1)."\n".
                        "HEADERS: ".var_export(getallheaders(),1));
    }

    return $fatalHandlerTitle;
}

function fatalHandlerInit($title="phpError") {
    global $fatalHandlerError, $fatalHandlerTitle;

    $fatalHandlerTitle = $title;
    $fatalHandlerError = error_get_last();

    set_error_handler( "fatalHandler" );
}

Теперь у меня есть проблема, когда, если память исчерпана, она не сообщает об этом каждый раз. Кажется, это зависит от того, сколько памяти используется. Я сделал скрипт для загрузки большого файла (занимает ~ 6.6M памяти) в бесконечном цикле. Setup1:

ini_set('memory_limit', '296M');

fatalHandlerInit("testing");

$file[] = file("large file"); // copy paste a bunch of times

В этом случае я получаю сообщение об ошибке, и оно умирает при загрузке 45 файлов.

Setup2 - то же самое, но изменить: ini_set ('memory_limit', '299M');

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

Кто-нибудь знает, почему и как это обойти?

0 голосов
/ 02 августа 2012

Очень интересная вещь, которую я обнаружил сегодня, когда столкнулся с подобной проблемой. Если вы используете следующее - он поймает ошибку с помощью вашего пользовательского обработчика ошибок функции / метода:

ini_set('display_errors', 'Off');
error_reporting(-1);

set_error_handler(array("Cmd\Exception\Handler", "getError"), -1 & ~E_NOTICE & ~E_USER_NOTICE);

Установив «display_errors» в «Выкл.», Вы можете поймать их, обработав их.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...