Обработка ошибок в PHP и исключения
Итак. Работа над 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%
Понравилась заметка? Подписывайся на обновления блога!
Смотрите также:




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