PHP: пользовательский обработчик ошибок-обработка синтаксического анализа и фатальных ошибок

Как я могу справиться анализа & смертельный ошибки с помощью таможни обработчик ошибок?

6 ответов


простой ответ: Вы не можете. Вижу руководство:

следующие типы ошибок не могут быть обрабатывается с помощью пользовательской функции: ПРИВОДИТЬ К ОШИБКЕ E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING и большая часть E_strict, поднятый в файле, где set_error_handler() называется.

для любой другой ошибки, вы можете использовать set_error_handler()

EDIT:

Так как кажется, что есть некоторые обсуждение этой темы, в отношении использования register_shutdown_function, мы должны взглянуть на определение обработки: для меня обработка ошибки означает улавливание ошибки и реагирование таким образом, что это "хорошо" для пользователя и базовые данные (базы данных, файлы, веб-сервисы и т. д.).

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


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

prepend.в PHP (этот файл будет автоматически добавлен ко всем скриптам php). Ниже приведены советы по добавлению файлов в PHP.
set_error_handler("errorHandler");
register_shutdown_function("shutdownHandler");

function errorHandler($error_level, $error_message, $error_file, $error_line, $error_context)
{
$error = "lvl: " . $error_level . " | msg:" . $error_message . " | file:" . $error_file . " | ln:" . $error_line;
switch ($error_level) {
    case E_ERROR:
    case E_CORE_ERROR:
    case E_COMPILE_ERROR:
    case E_PARSE:
        mylog($error, "fatal");
        break;
    case E_USER_ERROR:
    case E_RECOVERABLE_ERROR:
        mylog($error, "error");
        break;
    case E_WARNING:
    case E_CORE_WARNING:
    case E_COMPILE_WARNING:
    case E_USER_WARNING:
        mylog($error, "warn");
        break;
    case E_NOTICE:
    case E_USER_NOTICE:
        mylog($error, "info");
        break;
    case E_STRICT:
        mylog($error, "debug");
        break;
    default:
        mylog($error, "warn");
}
}

function shutdownHandler() //will be called when php script ends.
{
$lasterror = error_get_last();
switch ($lasterror['type'])
{
    case E_ERROR:
    case E_CORE_ERROR:
    case E_COMPILE_ERROR:
    case E_USER_ERROR:
    case E_RECOVERABLE_ERROR:
    case E_CORE_WARNING:
    case E_COMPILE_WARNING:
    case E_PARSE:
        $error = "[SHUTDOWN] lvl:" . $lasterror['type'] . " | msg:" . $lasterror['message'] . " | file:" . $lasterror['file'] . " | ln:" . $lasterror['line'];
        mylog($error, "fatal");
}
}

function mylog($error, $errlvl)
{
...do whatever you want...
}

PHP вызовет функцию errorHandler (), если он ловит ошибку в любом из сценариев. Если ошибка заставляет скрипт немедленно завершать работу, ошибка обрабатывается функцией shutdownHandler ().

это работает на сайте, который я разрабатываю. Я еще не тестировал его на производстве. Но в настоящее время он ловит все ошибки, которые я нахожу при его разработке.

Я считаю, что существует риск поймать одну и ту же ошибку дважды, по одному разу каждой функцией. Это может произойти, если ошибка, которую я обрабатываю в функция shutdownHandler () также была поймана функцией errorHandler ().

задачи:

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

2-Реализация обработки ошибок для всех вызовов MySQL.

3 - реализовать обработку ошибок для моего кода JavaScript.

важно Примечания:

1 - я использую следующую строку в своем php.ini для автоматического добавления вышеуказанного скрипта ко всем скриптам php:

auto_prepend_file = "/homepages/45/d301354504/htdocs/hmsee/cgi-bin/errorhandling.php"

он работает хорошо.

2-я регистрирую и разрешаю все ошибки, включая ошибки E_STRICT. Я верю в разработку чистого кода. Во время разработки мой php.файла ini следующие строки:

track_errors = 1
display_errors = 1
error_reporting = 2147483647
html_errors = 0

когда я буду жить, я изменю display_errors на 0, чтобы уменьшить риск того, что мои пользователи увидят уродливый PHP сообщение об ошибке.

надеюсь, это кому-то поможет.


вы можете отслеживать эти ошибки, используя такой код:

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

function shutdown() {
    $isError = false;

    if ($error = error_get_last()){
    switch($error['type']){
        case E_ERROR:
        case E_CORE_ERROR:
        case E_COMPILE_ERROR:
        case E_USER_ERROR:
            $isError = true;
            break;
        }
    }

    if ($isError){
        var_dump ($error);//do whatever you need with it
    }
}

register_shutdown_function('shutdown');

от PHP.net комментарии на страницеhttp://www.php.net/manual/en/function.set-error-handler.php

Я понял, что несколько человек здесь упомянули, что вы не можете захватить ошибки синтаксического анализа (Тип 4, E_PARSE). Это неправда. Вот как я это делаю. Надеюсь, это кому-то поможет.

1) Создайте " auto_prepend.php " файл в веб-корне и добавьте это:

<?php 
register_shutdown_function('error_alert'); 

function error_alert() 
{ 
        if(is_null($e = error_get_last()) === false) 
        { 
                mail('your.email@example.com', 'Error from auto_prepend', print_r($e, true)); 
        } 
} 
?> 

2) затем добавьте это " php_value auto_prepend_file / www / auto_prepend.php " для вашего .файл htaccess в корне web.

  • убедитесь, что вы изменить адрес электронной почты, и путь к файлу.

скрипт с ошибкой разбора всегда прерывается и его нельзя обработать. Поэтому, если скрипт вызывается напрямую или с помощью include / require, вы ничего не можете сделать. Но если он вызывается AJAX, flash или любым другим способом, там is обходной путь, как обнаружить ошибки синтаксического анализа.

мне нужно было это, чтобы справиться swfupload сценарий. Swfupload-это flash, который обрабатывает загрузку файлов и каждый раз, когда файл загружается, он вызывает скрипт обработки PHP для обработки filedata - но нет вывода браузера, поэтому скрипт обработки PHP нуждается в этих настройках для целей отладки:

  • предупреждения и уведомления ob_start (); в начале и сохранить содержимое в сеанс ob_get_contents (); в конце сценария обработки: это может быть отображено в браузере другим скриптом
  • фатальные ошибки register_shutdown_function (), чтобы установить сеанс с тем же трюком, что и выше
  • парсить ошибки если ob_get_contents () находится в конце сценария обработки и произошла ошибка разбора, сеанс не заполняется (он равен null). Сценарий отладки может обрабатывать его следующим образом:if(!isset($_SESSION["swfupload"])) echo "parse error";

Примечание 1 null означает is not set to isset()


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

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

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

3) директивы Php (также должны быть найдены в index.php) set_error_handler("myNonFatalErrorHandler"); #для того, чтобы поймать не фатальные ошибки register_shutdown_function('myShutdown'); #для того, чтобы ловить фатальные ошибки ini_set('display_errors', false); #чтобы скрыть ошибки, показанные пользователю php ini_set('log_errors',FALSE); #предполагая, что мы регистрируем ошибки сами ini_set('error_reporting', E_ALL); #мы хотели бы сообщить обо всех ошибках

пока в продукции (если я не ошибаюсь) мы можем уйти ini_set('error_reporting', E_ALL); как для того, чтобы иметь возможность регистрировать ошибку, в то же время ini_set('display_errors', false); убедитесь, что пользователю не отображаются ошибки.

что касается фактического содержания двух функций, о которых я говорю,myNonFatalErrorHandler и myShutdown, я не помещаю подробное содержание здесь, чтобы держать вещи простыми. Кроме того, другие посетители привели много примеров. Я просто показываю очень простую идею.

function myNonFatalErrorHandler($v, $m, $f, $l, $c){
 $some_logging_var_arr1[]="format $v, $m, $f, ".$err_lvl[$l].", $c the way you like";
 //You can display the content of $some_logging_var_arr1 at the end of execution too.
}

function myShutdown()
{
  if( ($e=error_get_last())!==null ){
      $some_logging_var_arr2= "Format the way you like:". $err_level[$e['type']].$e['message'].$e['file'].$e['line'];
  }
//display $some_logging_var_arr2 now or later, e.g. from a custom session close function
}

что касается $err_lvl, это может быть:

$err_lvl = array(E_ERROR=>'E_ERROR', E_CORE_ERROR=>'E_CORE_ERROR', E_COMPILE_ERROR=>'E_COMPILE_ERROR', E_USER_ERROR=>'E_USER_ERROR', E_PARSE=>'E_PARSE', E_RECOVERABLE_ERROR=>'E_RECOVERABLE_ERROR', E_WARNING=>'E_WARNING', E_CORE_WARNING=>'E_CORE_WARNING', E_COMPILE_WARNING=>'E_COMPILE_WARNING',
E_USER_WARNING=>'E_USER_WARNING', E_NOTICE=>'E_NOTICE', E_USER_NOTICE=>'E_USER_NOTICE',E_STRICT=>'E_STRICT');