Как я могу справиться с синтаксического анализа & фатальные ошибок с помощью пользовательский обработчик с ошибки?PHP: Пользовательский обработчик ошибок - обработка разобрана & фатальные ошибки
ответ
Простой ответ: вы не можете. Смотрите manual:
следующие типы ошибок не могут быть обрабатываются с определенной пользователем функции: 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
, вы не можете обрабатывать ошибку в коде, где он был вызван, что означает, что код все равно перестанет работать в точке, где происходит ошибка. Однако вы можете представить пользователю сообщение об ошибке вместо белой страницы, но вы не можете, например, отбросить все, что ваш код сделал до сбоя.
Вы можете отслеживать эти ошибки с помощью кода, как это:
(Разбираем ошибки могут быть пойманы только если они происходят в других файлов сценариев с помощью 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');
Вы протестировали его? –
Да, есть способ поймать E_PARSE! Поместите функцию обработчика ошибок в index.php и включите/укажите другой файл, где должна быть логика сайта! –
Единственный способ, которым я смог предотвратить появление ошибок анализа, заключался в том, чтобы включить скрипт, содержащий ошибку синтаксического анализа. – Melsi
Сценарий с ошибкой разбора всегда прерывается и его нельзя обрабатывать. Поэтому, если скрипт вызывается напрямую или include/require, вы ничего не можете сделать. Но если он вызывается AJAX, flash или каким-либо другим способом, то - это Обходное решение, как обнаружить ошибки синтаксического анализа.
Мне нужно было это обработать swfupload скрипт. SWFUpload является флэш, который обрабатывает загрузку файлов и файл каждый раз загружается, он требует обработки PHP скрипт для обработки FILEDATA - но там нет выхода браузера, поэтому сценарий обработки PHP нужны эти параметры для отладки:
- предупреждения и уведомления ob_start(); в начале и сохранить содержимое в сеансе ob_get_contents(); в конце сценария обработки: Это может быть отображен в браузере с помощью другого скрипта
- фатальные ошибки register_shutdown_function(), чтобы установить сеанс с тем же трюк, что и выше
- ошибки разбора если ob_get_contents() является который находится в конце скрипта обработки, и ранее была обнаружена ошибка анализа, сеанс не заполняется (он равен нулю). Сценарий отладки может обрабатывать его таким образом:
if(!isset($_SESSION["swfupload"])) echo "parse error";
Примечание 1null
означает is not set
к isset()
Из комментариев 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 в корневом каталоге.
- удостоверьтесь, что вы изменили адрес электронной почты и путь к файлу.
Это решение охватывает E_PARSE, E_COMPILE_ERROR и т. Д. Поэтому ответ Дэна Мына и руководство php.net ошибочны. Спасибо! – mgutt
Если вы используете FastCgi, вы не можете установить значение PHP в .htaccess. Вместо этого вы используете свой локальный файл php.ini и устанавливаете прямо auto_prepend_file = /www/auto_prepend.php – 2016-04-26 06:35:54
Фактически вы можете обрабатывать синтаксические разборки и фатальные ошибки. Верно, что функция обработчика ошибок, которую вы определили с помощью 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 - Мне нужно работать на функцию лучше журнала() для обработки ошибок грациозно. Поскольку я все еще в разработке, я в основном регистрирую ошибку в базе данных и повторяю ее на экране.
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.
Надеюсь, это поможет кому-то.
Кажется, что он не обрабатывает «Ошибки анализа» ... попробуйте следующее: echo «Cat»; echo "Dog" echo "Lion"; – Phantom007
Вы должны добавить файл для обработки ошибок разбора! – Dargmuesli
'E_DEPRECATED' и' E_USER_DEPRECATED' также должны быть включены в пользовательскую функцию обработчика ошибок. – Wh1T3h4Ck5
Из моего опыта вы можете поймать все типы ошибок, скрыть сообщение об ошибке по умолчанию и отобразить собственное сообщение об ошибке (если хотите). Ниже перечислены то, что вам нужно.
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);
#assuming мы регистрируем ошибки мы сами ini_set('error_reporting', E_ALL);
# мы хотели бы сообщить все ошибки
в то время как в производстве (если я не ошибаюсь), мы можем оставить ini_set('error_reporting', E_ALL);
как для того, чтобы иметь возможность войти ошибку, в то же время ini_set('display_errors', false);
будет следить за тем, чтобы n o пользователю отображаются ошибки.
Что касается фактического содержания двух функций, которые я говорю, 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');
Спасибо за добавление, что функции не могут быть в том же файле, что и ошибка. – Niclas
Лучше использовать [Закрытие] (http://php.net/manual/class.closure.php) в качестве обработчика ошибок, поскольку [названные функции могут быть переопределены] (http://php.net/manual/function.override -function.php # 50821) в настоящее время – Tino
На самом деле вы можете обрабатывать эти ошибки с функцией определенного пользователя. Все, что вам нужно сделать, это определить register_shutdown_function. См. Мой ответ ниже для рабочего примера, который я реализовал на своем веб-сайте. – jdias
Да, вы можете. Однако есть некоторые недостатки: см. Мое редактирование выше –
Благодарим за обновление. На самом деле вы можете сделать больше, чем представить пользователю сообщение об ошибке. Вы можете регистрировать сведения об ошибке, включая переменные, которые были установлены во время возникновения ошибки. Многие люди, которые используют общий хостинг, не имеют доступа к журналам Apache, например. Используя эту функцию, они смогут регистрировать критические ошибки и обращаться к ним. Кроме того, вы можете попытаться восстановить транзакции. Например, если ошибка возникла, когда пользователь пытался разместить заказ, вы можете сбросить все детали заказа в журнале или электронной почте и попытаться восстановить его в автономном режиме. – jdias