Как я могу обрабатывать ошибки parse и фатальные с помощью настраиваемого обработчика ошибок?
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()
РЕДАКТИРОВАТЬ:
Поскольку кажется, что есть некоторые дискуссии по этой теме, в отношении использования register_shutdown_function
, мы должны взглянуть на определение обработки: для меня обработка ошибки означает обнаружение ошибки и реагирование таким образом, чтобы это было «хорошо». для пользователя и базовые данные (базы данных, файлы, веб-службы и т. д.).
Используя register_shutdown_function
, вы не можете обработать ошибку из кода, в котором она была вызвана, а это означает, что код все равно перестанет работать в точке, где возникает ошибка. Однако вы можете представить пользователю сообщение об ошибке вместо белой страницы, но вы не можете, например, откатить все, что ваш код делал до сбоя.
include
s (не: require
). Так что все, что вам нужно, это небольшой .php
файл верхнего уровня, который выполняет всю перехват, который затем include
является настоящим файлом. Это относительно легко реализовать с помощью NginX
и php-fpm
(подсказка: cgi.fix_pathinfo=0
).
- person Tino; 24.08.2017
На самом деле вы можете обрабатывать синтаксический анализ и фатальные ошибки. Это правда, что функция обработчика ошибок, которую вы определили с помощью 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().
TODO:
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.
Я надеюсь, что это помогает кому-то.
E_DEPRECATED
и E_USER_DEPRECATED
также должны быть включены в пользовательскую функцию обработчика ошибок.
- person Wh1T3h4Ck5; 19.09.2017
Вы можете отслеживать эти ошибки, используя такой код:
(Ошибки синтаксического анализа можно обнаружить только в том случае, если они возникают в других файлах сценариев через 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');
index.php
, а затем включил ее в свой скрипт, используя include(index.php)
. Но он по-прежнему не может поймать ошибки синтаксического анализа (синтаксическая ошибка). Я не думаю, что это возможно без встраивания в php.ini.
- person Khurshid Alam; 20.08.2014
Из комментариев 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('[email protected]', 'Error from auto_prepend', print_r($e, true));
}
}
?>
2) Затем добавьте этот «php_value auto_prepend_file /www/auto_prepend.php» в ваш файл .htaccess в корневом каталоге веб-сайта.
- убедитесь, что вы изменили адрес электронной почты и путь к файлу.
По моему опыту, вы можете отловить все типы ошибок, скрыть сообщение об ошибке по умолчанию и отобразить собственное сообщение об ошибке (если хотите). Ниже перечислены вещи, которые вам нужны.
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');
ini_set('display_errors', false);
, чтобы скрыть отчеты PHP. Следует также отметить, что функция set_error_handler не нужна, так как обратный вызов register_shutdown_function получает даже ошибки E_NOTICE, такие как использование определенных констант, которые не были определены. При таком понимании обработка исключений (try/catch) не нужна для многих программ, которые останавливаются при первой обнаруженной ошибке.
- person David Spector; 31.01.2020
Скрипт с ошибкой синтаксического анализа всегда прерывается и не может быть обработан. Поэтому, если скрипт вызывается напрямую или с помощью include/require, вы ничего не можете сделать. Но если он вызывается с помощью AJAX, flash или любым другим способом, существует обходной путь для обнаружения ошибок синтаксического анализа.
Мне нужно было это для обработки скрипта swfupload. Swfupload — это флэш-память, которая обрабатывает загрузку файлов, и каждый раз, когда файл загружается, он вызывает скрипт обработки PHP для обработки файловых данных, но вывод браузера отсутствует, поэтому скрипту обработки PHP нужны эти настройки для целей отладки:
- предупреждения и уведомления ob_start(); в начале и сохранить содержимое в сеансе с помощью ob_get_contents(); в конце скрипта обработки: это может отображаться в браузере другим скриптом
- фатальные ошибки register_shutdown_function() для установки сеанса с тем же трюком, что и выше.
- ошибки синтаксического анализа, если ob_get_contents() расположен в конце скрипта обработки, а ошибка синтаксического анализа возникла раньше, сессия не заполняется (она равна нулю). Сценарий отладки может справиться с этим следующим образом:
if(!isset($_SESSION["swfupload"])) echo "parse error";
Примечание 1 null
означает от is not set
до isset()
php -l
? - person Milo LaMar   schedule 26.12.2018