PHP: перехват ошибок |
![]() |
Добавил(а) microsin | ||||||||||||||||||||||||||||||||||||||||||||||||
На серьезных сайтах странно видеть, когда ошибки выводятся пользователю в браузер в самых неожиданных местах. Почему они появляются - это отдельный разговор. Но почему они выводятся? Ведь текст ошибок является информацией для дебага и предназначена для разработчика, а не для клиента. Кроме того, именно эта служебная информация обычно помогает злым хакерам ломать сайт. В качестве классического примера можно привести вариант с выводом запроса при ошибке: "you have an error in query near WHERE id= "... Большое спасибо. Подставляем после "WHERE id=..." строку "0 OR 1>0" и запрос выполняется по всей таблице. Если запрос на удаление, то... сами понимаете, весело =). Поэтому я всегда переменные в запросах заключаю в кавычки. На всякий случай... Но я увлекся. Сегодня не об этом. Сегодня поговорим о том, как избежать вывода ошибок клиенту, сохранив при этом все сообщения вебмастеру на память. Пишем программу, делающую лог ошибок и прячем их от пользователя. Начнем, пожалуй, с краткого обзора видов ошибок в РНР. Таблица 1. Описания ошибок в PHP4
Нас интересуют те ошибки, которые мы можем перехватить. К ним относятся: E_WARNING, E_NOTICE и E_USER_*. Остальные виды ошибок перехвату не поддаются либо из-за того, что происходят они еще до окончания загрузки самого ядра РНР, либо из-за того, что происходят на этапе синтаксического анализа и компилирования РНР-кода, поэтому их вывод придется просто отключить: ini_set('display_errors',0); Но я предполагаю, что наши скрипты достаточно отлажены, чтобы в них не было элементарных синтаксических ошибок, поэтому потерять мы ничего не должны. По умолчанию уровень ошибок в РНР имеет значение E_ALL & ~E_NOTICE (или 2039 в числовой форме), что означает, что мы пропускаем мимо ушей замечания, но сообщаем о всех остальных ошибках. Кстати, сами разработчики рекомендуют включать на стадии разработки и E_NOTICE - помогает обнаружить потенциально опасные места. Поэтому изменим уровень вывода ошибок на E_ALL: error_reporting(E_ALL); Теперь переопределим хендлер (обработчик) ошибок и подставим вместо него нашу функцию user_log(), которая и будет заниматься теперь обработкой ошибок: set_error_handler('user_log'); Рассмотрим эту функцию подробней. Ей передаются 5 параметров: код ошибки Возвращать эта функция ничего не обязана. Так как мы собираемся просматривать потом лог ошибок, то надо сделать запись лога, например, в файл так, чтобы нам потом было удобно с ним работать. Итак, код с комментариями: < ?php /* Наша функция-хендлер */ function user_log ($errno, $errmsg, $file, $line) { // время события $timestamp = time(); Можно было бы, конечно, использовать более логичное для таких целей хранилище - базу, но ведь ошибки, в большинстве своем, возникают именно при работе с базой, поэтому я бы на нее не полагался. Собственно, это все. Остальное, я думаю, не составит для вас труда, особенно, если пользоваться функциями file(); & explode();. Еще разные мысли на эту тему: - при устаревании лога gz'иповать файл и складывать его в архив; Еще способ - просто в php.ini указать error_log = "log_file.log". Достоинство - простота, недостаток - Файл пишется не в нашем формате. Нельзя делать что угодно с этими ошибками. В случае с error_log = "имя_файла" - ошибки ТОЛЬКО пишутся в файл и ничего более. Да и не везде вас пустят к php.ini. Автор: Довгаль Антон [1]. [Ссылки] 1. PHP: перехват ошибок site:detail.phpclub.net. |