Домой / Обзор Linux / Оператор управления ошибками. Как включить или выключить отображение ошибок в PHP

Оператор управления ошибками. Как включить или выключить отображение ошибок в PHP


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

В скрипте PHP

1) В PHP есть всего лишь один оператор, который поддерживает систему управления ошибками - это знак @ . Он позволяет проигнорировать сообщение любое сообщение об ошибке. Его нужно ставить ПЕРЕД выражением, которое может её содержать.

В примере специально допущена ошибка, но она НЕ будет отображена

$value = @$var[$key];
2) Также можно перед проверяемым скриптом PHP можно вставить настройку параметра отображения ошибок (display_errors ). Он может приобретать значение либо On (показывать), либо Off (скрыть).

Ini_set("display_errors","On");
error_reporting("E_ALL");
И соответственно после кода, который проверялся на ошибки, выставить параметр обратно.

Ini_set("display_errors","Off");

Например, Вы хотите увидеть ошибки в скрипте

Ini_set("display_errors", "On"); // сообщения с ошибками будут показываться
error_reporting(E_ALL); // E_ALL - отображаем ВСЕ ошибки
$value = $var[$key]; // пример ошибки
ini_set("display_errors", "Off"); // теперь сообщений НЕ будет
Можно выставить наоборот (в верхнем off, а в нижнем on), чтобы в конкретном отрезке кода ошибки НЕ отображались.

В файле.htaccess

Чаще всего проблему решают именно указанием настроек в файле .htaccess , который располагается в корневой директории сайта. В строке php_flag display_errors нужно также выставить On или Off

Php_flag display_errors On
#показать все ошибки кроме предупреждений (Notice)
php_value error_reporting "E_ALL & ~E_NOTICE"

В файле php.ini

Как видите, параметр можно указать в нескольких местах. Однако, если у Вы хотите, чтобы целиком на сайте этот параметр имел определённое значение, то проще выставить его в файле php.ini.(к нему на хостинге не всегда может быть доступ), но в этом случае можно будет даже обойти настройки всего хостинга

В php.ini :

Error_reporting = E_ALL
display_errors On
В верхней строке выбираем все виды ошибок, в нижней даём добро на их отображение.

После правок необходимо перезапустить Apache, чтобы настройки были изменены и вступили в силу (graceful или restart):

Sudo apachectl -k graceful

В каком порядке обрабатывается параметр ошибок

В самом начале учитывается параметр php.ini , затем.htaccess , а после то, что указано непосредственно в скрипте PHP. Так что если что-то не сработало, то смотрим по цепочку выше, возможно, там настройка другая.

Как обычно спасибо за внимание и удачи! Надеюсь статья была полезна!

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...

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

Поскольку PHP является скриптовым языком программирования, то все ошибки, допущенные в коде, выявляются по ходу исполнения кода. Программисту PHP предстоит сталкиваться как со стандартными ошибками, присущими программированию в целом, так и с довольно скрытыми ошибками – такими как опечатки в именовании переменных.

Язык PHP предусматривает два механизма выявления ошибок в скрипте в процессе его выполнения: стандартный механизм ошибок PHP и механизм исключений. В PHP множество функционала использует стандартный механизм ошибок, поэтому не знать о нем нельзя. Поэтому в данной статье речь пойдет именно об этом механизме.

Стандартный механизм ошибок PHP довольно прост – если в процессе выполнения сценария интерпретатор PHP сталкивается с какой-либо ошибкой – он пытается известить об этом программиста. Однако настроек этого механизма предусмотрено довольно много, поэтому разобраться в них программисту, познающему PHP, довольно сложно.

Видим ошибки

Так, для того, чтобы PHP отображал ошибки прямо на странице, необходимо установить специальный параметр в коде:

ini_set("display_errors", 1); //display_errors отвечает за отображение ошибок прямиком на странице. Если 0 – ошибки не отображаются

Теперь, при возникновении какой-либо ошибки в скрипте, интерпретатор выведет информацию о ней на странице. Например, если запустить скрипт с несуществующей функцией:

ini_set("display_errors", 1);
echo "

Строка, которая будет отображена

";
echo abrakadabra();
echo "

Строка, которая не будет отображена из-за ошибки

";

то на странице отобразится такая ошибка:

Фатальная ошибка. Такого рода ошибка означает, что скрипт прерывает свою работу, и далее идущий код не будет выполнен.

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

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

Значение
Константа
Описание
Возможность
1
E_ERROR
Неустранимая ошибка
Нет
2
E_WARNING
Исправимая ошибка
Да
4
E_PARSE
Ошибка парсера
Нет
8
E_NOTICE
Потенциальная ошибка
Да
16
E_CORE_ERROR
Аналогично E_ERROR, но генерируется ядром PHP
Нет
32
E_CORE_WARNING
Аналогично E_WARNING, но генерируется ядром PHP Нет
64
E_COMPILE_ERROR
Аналогично E_ERROR, но генерируется Zend Engine
Нет
128
E_COMPILE_WARNING
Аналогично E_WARNING, но генерируется Zend Engine Нет
256
E_USER_ERROR
Аналогично E_ERROR, но инициируется вызовом trigger_error()
Да
512
E_USER_WARNING
Аналогично E_WARNING, но инициируется вызовом trigger_error() Да
1024
E_USER_NOTICE
Аналогично E_NOTICE, но инициируется вызовом trigger_error() Да
2048
E_STRICT
Сообщение от исполнительной среды с рекомендациями по улучшению качества кода (начиная с PHP5)
-
4096
E_RECOVERABLE_ERROR
Опасная, но не фатальная ошибка(например, несоответствие типа)
Да
8192
E_DEPRECATED
Предупреждение об использовании устаревшей функции или возможности
Да
16384
E_USER_DEPRECATED
Предупреждение об использовании устаревшей функции или возможности, инициированное в коде
Да
32767
E_ALL
Все ошибки
Нет

Для удобства предусмотрены константы, которые используются для определения уровня обработки ошибок, построения бит-маски. Константы имеют "говорящие" имена. Глядя на константу - мы можем сказать, что ошибка уровня E_PARSE возникает в случае синтаксической ошибки, E_NOTICE - это напоминание программисту о нарушении "хорошего стиля" программирования на PHP.

По умолчанию включено значение режима генерации сообщений об ошибках E_ALL & ~E_NOTICE , что соответствует выводу всех сообщений, не относящихся к категории E_NOTICE . Программист может гибко настроить, какие категории ошибок ему необходимо видеть на странице. Для того, чтобы изменить режим генерации ошибок, необходимо изменить конфигурационный параметр error_reporting . Чтобы включить отображение любых ошибок, необходимо задать данному параметру значение E_ALL :

Например, если запустить следующий код:

ini_set("display_errors", 1);
ini_set("error_reporting", E_ALL);

Мы получим ошибки сразу двух категорий (notice и warning):

Когда используется необъявленная переменная – появляется ошибка E_NOTICE . Когда соединение с базой данных MySQL (или другой) завершается неудачей - интерпретатор PHP сообщает об ошибке уровня E_WARNING .

Логируем ошибки

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

По умолчанию средствами языка PHP ошибки нигде не логируются. Чтобы это изменить, необходимо изменить конфигурационный параметр log_errors в 1 с 0:

ini_set("log_errors", 1);

В таком случае, ошибки автоматически будут записываться в файл, указанный в конфигурационном параметре error_log . Параметр error_log также можно изменить, указав путь к желаемому файлу, куда будут записываться ошибки:

ini_set("error_log", "/var/log/php_errors.log");

Так, для кода:

ini_set("display_errors", 1);
ini_set("error_reporting", E_ALL);
ini_set("log_errors", 1);
ini_set("error_log", __DIR__ . "/log.txt");
$db = mysql_connect($db_host, "user", "password");

В лог-файл записывается аналогичная информация, которая выводится на страницу:

PHP Notice: Undefined variable: db_host in Z:\home\test\www\index.php on line 7
PHP Warning: mysql_connect(): Access denied for user "user"@"localhost" (using password: YES) in Z:\home\test\www\index.php on line 7

Обрабатываем ошибки

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

Для того, чтобы перехватывать некритические ошибки в коде, достаточно реализовать и объявить собственную функцию и передать ее название в функцию set_error_handler . При этом, в реализованную функцию передаются 5 параметров:

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

Вывод

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

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

Итак, для начала давайте определимся, что такое ошибки в PHP.

PHP поддерживает следующие уровни ошибок:

E_ERROR
E_WARNING
E_PARSE
E_NOTICE
E_CORE_ERROR
E_CORE_WARNING
E_COMPILE_ERROR
E_COMPILE_WARNING
E_USER_ERROR
E_USER_WARNING
E_USER_NOTICE
E_ALL
E_STRICT

На самом деле — это просто константы, которые используются для определения уровня обработки ошибок, построения бит-маски. Константы имеют "говорящие" имена. Глядя на константу — мы можем сказать, что ошибка уровня E_PARSE возникает в случае синтаксической ошибки, E_NOTICE — это напоминание программисту о нарушении "хорошего стиля" программирования на PHP.

Несколько примеров:

Когда соединение с базой данных MySQL (или другой) завершается неудачей — интерпретатор PHP сообщает об ошибке уровня E_WARNING

Warning: mysql_connect(): Access denied for user: "VVingless@localhost" (Using password: YES) In /home/mysite/index.php (line 83)

Замечание: Для того чтобы интерпретатор PHP сообщал об ошибках — PHP должен быть настроен соответствующим образом: флаг display_errors должен быть включен — 1, директива error_reporting должна указывать на то, что необходимо отображать ошибки уровня E_WARNING (желательно конечно и другие). Если значения этих директив не удовлетворяют вашим требованиям — вы можете попробовать установить их самостоятельно, положив в папку со скриптом файл.htaccess (точка в начале имени обязательна) примерно такого содержания:

Php_flag display_errors on
php_value error_reporting "E_ALL & ~E_NOTICE"

Это означает, что сообщения об ошибках будут показываться, причем всех уровней, кроме E_NOTICE
Когда программист допускает синтаксическую ошибку — интерпретатор PHP сообщает об ошибке уровня E_PARSE

Parse error: parse error, unexpected ‘(‘, expecting T_STRING in /home/mysite/index.php on line 150

Но самые интересные для нас уровни ошибок — E_USER_ERROR и E_USER_WARNING. Как становится понятно из названия — это уровни ошибок, которые может устанавливать пользователь. Для этого существует функция trigger_error() — с её помощью, Вы можете сообщать пользователю о происшествии так, как это делает PHP.

Как известно из руководства по PHP — функция trigger_error() принимает два параметра.

void trigger_error (string error_msg [, int error_type])

Первый параметр — текстовое сообщение об ошибке, например "файл не найден". Второй параметр — определяет уровень ошибки. Функция trigger_error() работает только с семейством ошибок E_USER — это значит, что вы можете установить ошибку уровня E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE и не можете установить ошибку уровня E_WARNING. Второй параметр является не обязательным, и по умолчанию принимает значение E_USER_NOTICE.

Давайте попробуем:

Допустим, наши данные для ленты новостей хранятся в файле news.txt, и если файл не найден — необходимо сообщить об ошибке. Текст программы будет выглядеть примерно так:

if (!file_exists(‘/home/mysite/news.txt’)) {
trigger_error(‘News file not found’);
}

В результате интерпретатор PHP сообщит об ошибке уровня E_USER_NOTICE

Notice: News file not found in /home/mysite/index.php on line 47
Но что нам это даёт? Для начала то, что если в php.ini или файле.htaccess были установлены директивы

php_value log_errors "1"
php_value log_errors_max_len "1024"
php_value error_log "/home/mysite/my.log"
То в файл /home/mysite/my.log автоматически будет добавлена запись о происшествии.

PHP Notice: News file not found in /home/mysite/index.php on line 47
Далее, с помощью функции set_error_handler() мы можем установить свой собственный обработчик ошибок возникающих во время выполнения PHP скрипта.

Как известно из мануала — в PHP 4 функция принимает один единственный строковый параметр — имя функции, которая будет выполняться каждый раз, когда происходит ошибка. PHP 5 даёт возможность установить ещё один параметр — тип ошибок которые будут обрабатываться с помощью нашего обработчика. Функция возвращает строку — имя функции обработчика, который был установлен до этого момента.

string set_error_handler (callback error_handler [, int error_types])

устанавливаем так

set_error_handler ("my_error_handler");
Пользовательская функция, которая будет обрабатывать ошибки, может принимать следующие входные параметры:

— код уровня ошибки
— строковая интерпретация ошибки
— имя файла, в котором произошла ошибка
— строка, в которой произошла ошибка

Следует так же заметить, что эта функция не может обрабатывать ошибки уровней E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING

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

Итак, объявляем нашу функцию

function my_error_handler($code, $msg, $file, $line) {
}

Замечание: каждый более-менее объемный скрипт обычно разделяется на несколько файлов для удобства работы с ним. Как организовывать модульность программы — тема отдельно разговора. Сейчас же, я хочу лишь посоветовать выделять общие настройки в отдельный файл, который будет подключаться в начале программы с помощью инструкции include, либо с помощью директивы auto_prepend_file. В этот файл можно поместит и наш обработчик. Установка обработчика ошибок должна осуществится как можно ближе к началу программы, желательно в самом начале.
Для того чтобы убедится что это действительно работает — создадим новый PHP файл, и попробуем запустить его

Содержимое файла myerrortest.php

n"; echo "$file ($line)"; } set_error_handler("my_error_handler"); if (!file_exists("/home/mysite/news.txt")) { trigger_error("News file not found"); } ?>

Результат обработки данного файла будет таким:

Произошла ошибка News file not found (1024)
/home/mysite/myerrortest.php (12)
Теперь у нас есть функция, которая получает данные обо всех происходящих ошибках. Подумаем, как мы можем это использовать.

Будем обрабатывать ошибки уровней
E_ERROR
E_WARNING
E_NOTICE
E_USER_ERROR
E_USER_NOTICE

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

Что касается остальных двух — как Вы уже догадались — они могу там пригодиться. Мы сами будем вызывать ошибки этих уровней в случае необходимости. Допустим — ошибки уровня E_USER_ERROR — будем вызывать в случае, когда сообщение об ошибке должно попасть в log-файл и быть отправлено на e-mail администратору (например — ошибка при выполнении SQL запроса, или отсутствии парв доступа к необходимому файлу). Ошибки уровня E_USER_NOTICE будут вызываться при возникновении "лёгких" ошибок (например — пользователь некорректно заполнил форму, или запросил из базы несуществующую запись).

Теперь наша функция обработки ошибок будет выглядеть примерно так:

// Немного предварительных настроек // устанавливаем режим отображения ошибок // отображать все ошибки, кроме E_NOTICE error_reporting (E_ALL & ~E_NOTICE); // эта константа отвечает за // включение/выключение режима отладки // во время отладки - сообщения не отсылаются // по почте, а просто печатаются на экран define("DEBUG", 0); // это глобальная переменная, в которой // будет храниться сообщение, которое // должен видеть пользователь $MSG = ""; // e-mail разработчика, куда отправлять ошибки define("ADM_EMAIL","[email protected]"); // log-файл define("LOGFILE","/home/mysite/mylog.log"); // разница во времени с сервером (в секундах) define("TIMEOFFSET", 0); // сама функция function my_error_handler($code, $msg, $file, $line) { // глобальная переменная, в которую будет // записываться сообщение об ошибке. global $MSG; // пропускаем ошибки уровня E_NOTICE // и игнорируем ошибки, если режим сообщения об ошибках отключен if (($code == E_NOTICE) or (error_reporting() == 0)) { return; } // если мы вызвали ошибку уровня E_USER_NOTICE - просто // записать текст ошибки в глобальную переменную $MSG // и прекратить выполнение функции if ($code == E_USER_NOTICE) { $MSG = $msg; Return; } // если ошибка уровня E_ERROR - печатаем текст ошибки // и завершаем выполнение скрипта if ($code == E_ERROR) { die ("
ERROR: ".$msg."
In ".$file." (line ".$line.")
"); } // если ошибка уровня E_WARNING - печатаем текст ошибки // и прекращаем выполнение функции if ($code == E_WARNING) { echo "
WARNING: ".$msg."
In ".$file." (line ".$line.")
"; Return; } // если ошибка уровня E_USER_ERROR if ($code == E_USER_ERROR) { // записываем в переменную $MSG текст, о том что произошла ошибка, // причины сообщать не будем, только сообщим что подробности // отправлены на e-mail кому следует. $MSG = "Критическая Ошибка: действие выполнено небыло.
Сообщение об ошибке было отправлено разработчику."; // подробности записываем в переменную $text $text = $msg."
"."Файл: ".$file." (".$line.")"; // Если константа DEBUG установлена в 1 - печатаем информацию об // ошибке на экран, если нет - отправляем текст ошибки почтой // функция error_mail() и пишем в log - функция error_writelog() if (DEBUG == 1) { error_print($text); } else { error_mail($text); error_writelog($text); } Return; } } // устанавливаем обработчик set_error_handler("my_error_handler"); Теперь описываем служебные функции // ф-я печатает ошибку на экран function error_print($text) { echo $text."

"; } // ф-я отправляет ошибку почтой function error_mail($text) { $text = str_replace("
", "n", $text); $info = "Время: ".get_datetime()."nRemote IP:".get_ip()."n"; mail(ADM_EMAIL, "Error reporting", $info.$text); } // ф-я пишет ошибку в лог function error_writelog($text) { $text = str_replace("
", "t", $text); if (@$fh = fopen(LOGFILE, "a+")) { fputs($fh, get_datetime()."t".get_ip()."t".$text."n"); fclose($fh); } } // получаем время, с учётом разницы во времени function get_time() { return(date("H:i", time () + TIMEOFFSET)); } // получаем дату, с учётом разницы во времени function get_date() { return(date("Y-m-d", time () + TIMEOFFSET)); } // получаем дату и время, с учётом разницы во времени function get_datetime() { return get_date()." ".get_time(); } // получаем IP function get_ip() { return($_SERVER["REMOTE_ADDR"]); } И наконец пример использования // ф-я записывает новость в файл function write_news($title, $text) { $news_file = "/home/mysite/news.txt"; // проверяем наличие заголовка - ошибка не критическая if (!trim($title)) { // для того чтобы определить что функция завершилась // неудачей - необходимо вернуть false. Функция // trigger_error() - возвращает true, мы будем // возвращать её инвертированный результат return !trigger_error("Необходимо указать заголовок новости"); } // проверяем наличие текста новости - ошибка не критическая if (!trim($text)) { return !trigger_error("Необходимо указать текст новости"); } // проверяем наличие файла в который будем писать // если файл не найден - возникает критическая ошибка if (!file_exists($news_file)) { return !trigger_error("Файл базы новостей не найден!", E_USER_ERROR); } // ...тут предварительная обработка данных... // записываем новость $fh = fopen($news_file, "a+"); fputs($fh, $title."t".$text."n"); fclose($fh); // если всё нормально - функция возвращает true return true; } // пытаемся записать новость // эти данные могут приходить из web-формы $res = write_news("Моя новость", "Текст моей новости"); if ($res === false) { // если вернулся false - печатаем ошибку echo $MSG; } else { // если всё в порядке - можно сообщить об этом // а лучше отфорвардить пользователя куда-нибудь. echo "Новость была добавлена"; }

Для того чтобы пример заработал — просто скопируйте в PHP-файл три предыдущих блока кода. Не забудьте установить права доступа на log-файл 777 для того чтобы скрипт мог с ним работать, прописать правильные пути и указать свой e-mail. Вы можете включить режим отладки установкой переменной DEBUG в 1.


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


Ошибки в 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 администратора и делает другие полезные операции.

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