PHP: Обработка ошибок
| Автор: | Артемьев Сергей Игоревич | 
| ICQ: | 438856621 | 
| email: | _spin_@bk.ru | 
В предыдущем уроке мы рассмотрели основы обработки исключений и различия между исключениями и ошибками. В этом уроке бы изучим опрядок обработки ошибок.
Ошибки в PHP можно разделить пользовательские и системные. К сожалению, перехватить системные ошибки стандартными средствами невозможно и единственный способ борьбы с ними - грамотное написание и отладка кода. Единственное, что можно (и нужно) сделать - запретить вывод в браузер любых сообщений об ошибках. Делается это при помощи функции error_reporting(). динственный параметр этой функции определяет какие ошибки разрешено выводить в браузер.
<?php
	// функцию лучше всего вызывать 
	// в самом начале, до выполнения 
	// других выражений
    error_reporing(E_ALL ^ E_NOTICE);
	// код скрипта
?>
Параметр функции может быть комбинацией следующих констант
| Константа | Описание | 
|---|---|
| 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 | Критические ошибки, допускающие дальнейшее исполнение кода. | 
Например:
<?php
	// отображать всё
    error_reporting(E_ALL);
	// отображать всё, кроме замечаний
	error_reporting(E_ALL ^ E_NOTICE);
	
	// отображать только замечания и предупреждения
	error_reporting(E_NOTICE | E_WARNING);
	// не отображать ничего
	error_reporting(0);
?>
Иногда возникают случаи, когда надо запретить вывод ошибок не для всего скрипта, а лишь для его части. В этом случае необходимо пользоваться оператором подавления ошибок "@" (собака). Будучи поставлен перед выражением, этот оператор запрещает вывод на зкран всех сообщений, предупреждений или замечаний, генерируемых выражением. Например:
<?php
	
    $mailed = @mail('', '', '');
	// если письмо не будет отправлено
	// но функция просто вернёт false,
	// не отображая никаких ошибок
	if(!$mailed)
		trigger_error('Ошибка отправки письма');
?>
Пользовательские ошибки могут быть без проблем перехвачены и обработаны, причем обработка ошибок построена таким образом, что может выполняться без завершения основного скрипта.
Для генерации ошибки служит функция trigger_error(), которой передаётся два параметра - тип ошибки и собственно её текст. Тип ошибки определяется стандартными константами, рассмотренными выше.
Например:
<?php
    if(!isset($user_name) || trim($user_name) == '')
        trigger_error(E_USER_ERROR, 
			'Имя пользователя не указано');
    if(!isset($user_passwd) || trim($user_passwd) == '')
        trigger_error(E_USER_ERROR, 
			'Пароль пользователя не указан');
?>
Вызов функции trigger_error не приводит к аварийному завершению скрипта, а значит весь последующий код будет нормально исполняться. Если же прервать выполнение всё-таки необходимо, то программист должен сделать это "вручную", используя средства языка.
Как и для исключений, для ошибок можно установить собственный обработчик. Делается это при помощи функции set_error_handler(), которой передаётся имя функции-обработчика и список типов ошибок, для которых эта функция вызывается. Функция имеет четыре параметра: номер ошибки, текст ошибки, имя файла и номер строки, где ошибка произошла. Например:
<?php
function specialHandler($errno, $errstr, 
						$errfile, $errline)
{
   switch ($errno)
   {
      case E_USER_ERROR:
            echo "Критическая ошибка: <br />\n" .
              "Номер: $errno <br />\n" .
              "Текст: $errstr <br />\n" .
              "Файл: $errfie <br />\n" .
              "Строка: $errline <br />\n";
            exit(1);
      break;
      case E_USER_WARNING:
          echo "Предупреждение: [$errno] $errstr<br />\n";
      break;
      case E_USER_NOTICE:
          echo "Замечание: [$errno] $errstr<br />\n";
      break;
      default:
          echo "Неизвестная ошибка: [$errno] $errstr<br />\n";
      break;
	}
   return true;
}
// указываем, что нам необходимо
// проверять все возникающие ошибки
set_error_handler('specialHandler', E_ALL);
?>
Если функция обработки ошибки возвращает true, то внутренний обработчик PHP не вызывается, а если false - то после выхода из пользовательской процедуры ошибка будут передана в стандартный внутренний обработчик. Это позволяет программисту реагировать только на часть возникающих ошибок, отдавая остальное старндартным обработчикам PHP.
Восстановить предыдущий обработчик можно, вызвав функцию restore_error_handler():
<?php
	set_error_handler('myFunction');
	// 
	// код
	//
	restore_error_handler();
?>
Таким способом можно включать и выключать обработчики ошибок по мере необходимости. Но злоупотреблять такими операциями не стоит - слишком высока вероятность запутаться и перепутать обработчики. В большинстве случаев достаточно одного, но хорошо написанного обработчика, который пишет ошибки в лог-файл или базу данных, пересылает их на email администратора и делает другие полезные операции.
Обработка ошибок - один из важнейших элементов написания скриптов. Некачественно написанный срипт может стать не только головной болью веб-мастера или администратора сайта. "Бажный" (от слова "баг" - ошибка) скрипт представляет серьёзную угрозу безопасности. В руках умелого взломщика текст ошибки превращается в отмычку, открывающую доступ ко всему содержимому сайта, а может быть и сервера.
