Обработка ошибок в PHP и исключения

9 августа 2008

Итак. Работа над RedBox ведется полным ходом. Сегодня расскажу про обработку ошибок.

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

Почему? С одной стороны, пользователя, зашедшего на сайт не интересует по какой причине он не работает. Ошибка MySQL, или PHP, или другая? Ему по барабану. Он пришел за информацией, а ее нет. Важнее подсказать ему, что делать (”Загляните через пару минут”, “Воспользуйтесь зеркалом нашего сайта по адресу…”). С другой - ни к чему светить информацию, которую он видеть не должен (тексты запросов, document root и пр.).

Разделение вывода

Начнем со второй проблемы. Ее я решил очень просто: в настройках сайта, имеется специальная константа debug_mode. Если она == 1 - выводим всю инфу в браузер, в остальных случаях - показываем пользователю текст (”Упс, у нас ошибочка” или подобное). Еще у меня реализована отсылка сообщений на почту в случае возникновения некоторых ошибок.

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

Ошибки или исключения?

До появления 5-ой версии PHP все ошибки приходилось обрабатывать разработчику. Каждый выходил из этой ситуации по-разному. Кто-то просто писал:

1
die('Ашыпка!!!');

Более продвинутые товарищи писали что-то наподобие этого:

1 2
echo 'Ашыпка!!!';
return false;

Самые умные -

1
trigger_error('Ашыпка!!!', E_USER_ERROR);

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

С появлением механизма исключений все сильно упростилось:

1 2 3 4 5 6 7 8 9 10 11
try {
	// Код
	if (/* какая-то проверка */) {
		throw new Exception('Ашыпка!!!', 0)
	}
}
catch (Exception $e) {
	// обрабатываем
	// например, просто выводим
	echo $e // тут работает "магический" метод __toString класса Exception
}

Причем можно определять классы-потомки от Exception и строить обработку ошибок на основе этих классов:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
class SeriosErrorException extends Exception;
class SomeTinyErrorException extends Exception;
try {
	// Код
	if (/* какая-то проверка */) {
		throw new SeriosErrorException('Сурьезная ашыпка!!!', 0)
	}
 
	if (/* еще какая-то проверка */) {
		throw new SomeTinyErrorException('Так себе ошибочка!!!', 0)
	}
}
catch (SeriosErrorException $e) {
	// обрабатываем
}
catch (SomeTinyErrorException $e) {
	// обрабатываем
}

Т.е. первый блок catch ловит только ошибки класса SeriosErrorException, все остальные “спускаются ниже”.

Вывод пользовательских ошибок

Пару слов о том, как выводятся ошибки в RedBox CMS.

Для таких ошибок создан класс UserException примерно следующего содержания:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
class UserException extends Exception {
	private $message_array = array(
		// коды ошибок
	);
	private $info;
 
	public function __construct($code, $info = NULL) {
		$this->info = $info;
		parent::__construct($this->message_array[$code], $code);
	}
 
	public function getText() {
		// Вывод ошибки в виде текста
	}
 
	public function getHtml() {
		// Вывод ошибки в виде HTML
	}
}

Например ошибка запроса к БД кидается следующим образом:

1
throw new UserException(1202, array('mysql' => $this->_query, 'text' => mysql_error()));

В режиме отладки это отображается так:

(для подсветки я использую GeSHi)

Вывод стандартных ошибок

По-умолчанию, PHP не очень разговорчив и выдает такие сообщения:

1
Warning: Wrong parameter count for strpos() in /usr/home/knave11t/ab.ru/WWW/inc/classes/News.class.php on line 52

Я предлагаю “переделывать” все ошибки в исключения с помощью функции set_error_handler. А дальше ловить эти исключения и обрабатывать их.

Для таких целей я использую класс, разработанный Дмитрием Котеровым.

Популярность: 13%

Понравилась заметка? Подписывайся на обновления блога!

Добавить в закладки:google.com bobrdobr.ru del.icio.us technorati.com linkstore.ru news2.ru rumarkz.ru memori.ru moemesto.ru
Категории: Интернет, Разработка Теги: , , ,
Смотрите также:

Комментарии
11 августа 2008

ивзращенец :))

пишет Alex_K
12 августа 2008

Ну-ка, ну-ка, покажи как ты их обрабатываешь. :)

пишет Knave

RSS-лента комментариев к этой записи. TrackBack URI

Оставить комментарий

(обязательно)

(обязательно)


Спамер, осторожно! — спамить бесполезно!