Оператор управления ошибками. Предыдущие сообщения об ошибках


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


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

Параметр функции может быть комбинацией следующих констант

Константа Описание
E_ERROR Критические ошибки, прерывающие выполнение скрипта (например, ошибка выделения памяти)
E_WARNING Предупреждения
E_PARSE Синтаксические ошибки исходного кода
E_NOTICE Замечания
E_CORE_ERROR Критические ошибки, возникающие на этапе запуска исполнения скрипта
E_CORE_WARNING Предупреждения, возникающие на этапе запуска
E_COMPILE_ERROR Ошибки компиляции
E_COMPILE_WARNING Предупреждения компиляции
E_USER_ERROR Пользовательские ошибки, созданные с помощью функции trigger_error()
E_USER_WARNING Пользовательские предупреждения, созданные с помощью функции trigger_error()
E_USER_NOTICE Пользовательские замечания, созданные с помощью функции trigger_error()
E_ALL Все возможные ошибки, предупреждения и замечания
E_STRICT Замечания времени выполнения
E_RECOVERABLE_ERROR Критические ошибки, допускающие дальнейшее исполнение кода.

Например:

Иногда возникают случаи, когда надо запретить вывод ошибок не для всего скрипта, а лишь для его части. В этом случае необходимо пользоваться оператором подавления ошибок "@" (собака). Будучи поставлен перед выражением, этот оператор запрещает вывод на зкран всех сообщений, предупреждений или замечаний, генерируемых выражением. Например:

Пользовательские ошибки могут быть без проблем перехвачены и обработаны, причем обработка ошибок построена таким образом, что может выполняться без завершения основного скрипта.

Для генерации ошибки служит функция trigger_error() , которой передаётся два параметра - тип ошибки и собственно её текст. Тип ошибки определяется стандартными константами, рассмотренными выше.

Например:

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

Как и для исключений, для ошибок можно установить собственный обработчик. Делается это при помощи функции set_error_handler() , которой передаётся имя функции-обработчика и список типов ошибок, для которых эта функция вызывается. Функция имеет четыре параметра: номер ошибки, текст ошибки, имя файла и номер строки, где ошибка произошла. Например:

\n" . "Номер: $errno
\n" . "Текст: $errstr
\n" . "Файл: $errfie
\n" . "Строка: $errline
\n"; exit(1); break; case E_USER_WARNING: echo "Предупреждение: [$errno] $errstr
\n"; break; case E_USER_NOTICE: echo "Замечание: [$errno] $errstr
\n"; break; default: echo "Неизвестная ошибка: [$errno] $errstr
\n"; break; } return true; } // указываем, что нам необходимо // проверять все возникающие ошибки set_error_handler("specialHandler", E_ALL); ?>

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

Восстановить предыдущий обработчик можно, вызвав функцию restore_error_handler():

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

Обработка ошибок - один из важнейших элементов написания скриптов. Некачественно написанный срипт может стать не только головной болью веб-мастера или администратора сайта. "Бажный" (от слова "баг" - ошибка) скрипт представляет серьёзную угрозу безопасности. В руках умелого взломщика текст ошибки превращается в отмычку, открывающую доступ ко всему содержимому сайта, а может быть и сервера.

PHP поддерживает один оператор управления ошибками: знак @. В случае, если он предшествует какому-либо выражению в PHP-коде, любые сообщения об ошибках, генерируемые этим выражением, будут проигнорированы.

Если вы установили собственную функцию обработки ошибок с помощью set_error_handler() , то она все равно будет вызвана, однако, если внутри этой функции будет вызвана функция error_reporting() , то она вернет 0, если функция, вызвавшая данную ошибку, была подавлена с помощью @.

В случае, если установлена опция track_errors , все генерируемые сообщения об ошибках будут сохраняться в переменной $php_errormsg . Эта переменная будет перезаписываться при каждой новой ошибке, поэтому в случае необходимости проверяйте ее сразу же.

// Преднамеренная ошибка при работе с файлами
$my_file = @ file ("non_existent_file" ) or
die ("Ошибка при открытии файла: сообщение об ошибке было таким: " $php_errormsg "" );

// работает для любых выражений, а не только для функций
$value = @ $cache [ $key ];
// В случае если ключа $key нет, сообщение об ошибке (notice) не будет отображено

?>

Замечание : Оператор @ работает только с выражениями . Есть простое правило: если что-то возвращает значение, значит вы можете использовать перед ним оператор @. Например, вы можете использовать @ перед именем переменной, произвольной функцией или вызовом include , константой и так далее. В то же время вы не можете использовать этот оператор перед определением функции или класса, условными конструкциями, такими как if , foreach и т.д.

Также ознакомьтесь с описанием функции error_reporting() и разделом руководства Обработка ошибок и функции логирования .

Внимание

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

12 years ago

To suppress errors for a new class/object:

// Tested: PHP 5.1.2 ~ 2006-10-13

// Typical Example
$var = @ some_function ();

// Class/Object Example
$var = @new some_class ();

// Does NOT Work!
//$var = new @some_class(); // syntax error
?>

I found this most useful when connecting to a
database, where i wanted to control the errors
and warnings displayed to the client, while still
using the class style of access.

14 years ago

Better use the function trigger_error() ()
to display defined notices, warnings and errors than check the error level your self. this lets you write messages to logfiles if defined in the php.ini, output
messages in dependency to the error_reporting() level and suppress output using the @-sign.

8 years ago

If you use the ErrorException exception to have a unified error management, I"ll advise you to test against error_reporting in the error handler, not in the exception handler as you might encounter some headaches like blank pages as error_reporting might not be transmitted to exception handler.


{
}

function catchException ($e )
{
{
return;
}

// Do some stuff
}

?>

It would be better to do:

Function exception_error_handler ($errno , $errstr , $errfile , $errline )
{
if (error_reporting () === 0 )
{
return;
}

Throw new ErrorException ($errstr , 0 , $errno , $errfile , $errline );
}

Set_error_handler ("exception_error_handler" );

function catchException ($e )
{
// Do some stuff
}

Set_exception_handler ("catchException" );

?>

4 years ago

While you should definitely not be too liberal with the @ operator, I also disagree with people who claim it"s the ultimate sin.

For example, a very reasonable use is to suppress the notice-level error generated by parse_ini_file() if you know the .ini file may be missing.
In my case getting the FALSE return value was enough to handle that situation, but I didn"t want notice errors being output by my API.

TL;DR: Use it, but only if you know what you"re suppressing and why.

2 years ago

What is PHP"s behavior for a variable that is assigned the return value of an expression protected by the Error Control Operator when the expression encounteres an error?

Based on the following code, the result is NULL (but it would be nice if this were confirmed to be true in all cases).

$var = 3 ;
$arr = array();

$var = @ $arr [ "x" ]; // what is the value of $var after this assignment?

// is it its previous value (3) as if the assignment never took place?
// is it FALSE or NULL?
// is it some kind of exception or error message or error number?

Var_dump ($var ); // prints "NULL"

?>

5 years ago

I was wondering if anyone (else) might find a directive to disable/enable to error operator would be a useful addition. That is, instead of something like (which I have seen for a few places in some code):

If (defined (PRODUCTION )) {
@function();
}
else {
function();
}

?>

There could be something like this:

If (defined (PRODUCTION )) {
ini_set ("error.silent" , TRUE );
}
else {
ini_set ("error.silent" , FALSE );
}

?>

12 years ago

If you want to log all the error messages for a php script from a session you can use something like this:
session_start ();
function error ($error , $return = FALSE ) {
global $php_errormsg ;
if(isset($_SESSION [ "php_errors" ])) {
$_SESSION [ "php_errors" ] = array();
}
$_SESSION [ "php_errors" ] = $error ; // Maybe use $php_errormsg
if($return == TRUE ) {
$message = "" ;
foreach($_SESSION [ "php_errors" ] as $php_error ) {
$messages .= $php_error . "\n" ;
}
return $messages ; // Or you can use use $_SESSION["php_errors"]
}
}
?>
Hope this helps someone...

Я пытаюсь разобрать HTML5-код, поэтому я могу установить атрибуты / значения в коде, но, похоже, DOMDocument (PHP5.3) не поддерживает теги, такие как