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


Как я могу справиться parse & fatal ошибки с помощью custom обработчик ошибок?

6 51

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(). Вот что у меня работает на моем сайте:

File добавить.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 или любым другим способом, там и обходной путь, как обнаружить ошибки синтаксического анализа.

мне нужно, чтобы обрабатывать 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";

Примечание 1null означает is not set до 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');