CodeIgniter предоставляет неплохие возможности по обработке ошибок, но мне они показались недостаточными по следующим причинам:
Будем это исправлять =)
Указываем обработчик исключений в файле /system/codeigniter/CodeIgniter.php
рядом со строчкой
теперь при возникновении исключения будет вызываться метод _exception_handler2 из файла /system/codeigniter/Common.php.
А вот собственно и сам метод:
Для того чтобы админстратор получал уведомление о ошибках на сайте на почтовый ящик, необходимо в файле /system/application/config/config.php указать почтовый адрес администратора:
Если вы не хотите чтобы сообщения отсылались — не указывайте этот параметр или оставьте его пустым.
Расширяем базовый класс Exceptions — в директории /system/application/libraries/
создаем файл MY_Exceptions.php со следующим содержимым:
Не забывайте. что для включения механизма ведения логов необходимо в файле /system/application/config/config.php указать у параметра log_threshold значением '1'.
Вы можете скачать исходники (Файлы CodeIgniter.php и Common.php от CodeIgniter 1.7.2)
Код довольно простой — думаю что все ясно по исходникам.
Если все таки вопросы возникнут — с удовольствием отвечу в комментариях.
В комментариях Mordred посоветовал использовать хуки вместо того чтобы править файлы ядра для вызова кода установки обработчика исключений и самого обработчика — спасибо за совет, я так и поступил.
Для начала надо включить механизм куков, для этого в файле /system/application/config/config.php параметр enable_hooks устанавливаем в TRUE:
Затем устанавливаем сам хук в файле /system/application/config/hooks.php пишем:
Данный код означает что при старте системы будет вызыван метод addExceptionHandler из файла /system/application/hooks/exception_hook.php. Вот содержимое этого файла:
В итоге файлы ядра фреймворка остаются нетронутыми.
Скачать новые исходники можно здесь.
Заодно были сделаны небольшие доработки — если ошибка возникала до загрузки контроллера — не срабатывала отсылка уведомлений админу, так как нужные классы для этого загружены не были, теперь стоит проверка и если нужный класс не загружен, то загружаем тогда его, плюс правки по мелочи.
Оригинал статьи
- отсутствует возможность обработки исключений
- отсутствует возможность уведомлять администратора сайта о возникающих ошибках через почту
- довольно скудная информацию о возникающих ошибках (в фреймворке с которым я работал раньше текст ошибки дополняется дампом глобальных переменных, что очень сильно облегчает процесс отладки, хотелось бы подобную схему увидеть и в CodeIgniter)
Будем это исправлять =)
Обработка исключений (см. ниже вариант без правки файлов ядра)
Указываем обработчик исключений в файле /system/codeigniter/CodeIgniter.php
set_exception_handler('_exception_handler2');
рядом со строчкой
set_error_handler('_exception_handler');
теперь при возникновении исключения будет вызываться метод _exception_handler2 из файла /system/codeigniter/Common.php.
А вот собственно и сам метод:
/** * Обработчик исключений * */ function _exception_handler2($errstr) { $error =& load_class('Exceptions'); // Выводим текст об исключении на экран echo $error->show_error('error', nl2br($errstr)); // Should we log the error? No? We're done... $config =& get_config(); if ($config['log_threshold'] == 0) { return; } // Пишем сообщение в лог $error->log_exception('Exception', $errstr, '', ''); exit; }
Уведомление по почте и дополнительная информация по ошибкам
Для того чтобы админстратор получал уведомление о ошибках на сайте на почтовый ящик, необходимо в файле /system/application/config/config.php указать почтовый адрес администратора:
/* |-------------------------------------------------------------------------- | Уведомление администратора об ошибках на сайте |-------------------------------------------------------------------------- | | Если вы хотите чтобы администратору приходили письма о возникающих ошибках и исключениях | Укажите у следующего параметра значением адрес почтового ящика администратора | */ $config['log_to_email'] = 'admin@site.ru';
Если вы не хотите чтобы сообщения отсылались — не указывайте этот параметр или оставьте его пустым.
Расширяем базовый класс Exceptions — в директории /system/application/libraries/
создаем файл MY_Exceptions.php со следующим содержимым:
class MY_Exceptions extends CI_Exceptions { /** * Exception Logger * * Метод заменяет базовый добавляя возможности * отсылать сообщению администратору сайта о ошибках * и выводить дополнительную информацию в лог * * @access private * @param string the error severity * @param string the error string * @param string the error filepath * @param string the error line number * @return string */ function log_exception($severity, $message, $filepath, $line) { // Отсылаем сообщение администратору сайта $this->adminmail($message); $severity = ( ! isset($this->levels[$severity])) ? $severity : $this->levels[$severity]; // Дополняем текст сообщения дампам переменных окружения $message .= "\n" . $this->GetGlobalVariables() . $filepath.' '.$line . "\n\n"; log_message('error', 'Severity: '.$severity.' --> '.$message, TRUE); } /** * 404 Page Not Found Handler * * Метод дополняет базовый возможностю отсылать администратору сообщение * в случае возникновения ошибки * * @access private * @param string * @return string */ function show_404($page = '') { // Отсылаем сообщение $message = '404 Page Not Found --> '.$page; $this->adminmail($message); parent::show_404($page); } /** * Возвращает дамп переменных окружения * * @return string дамп переменных окружения */ function GetGlobalVariables() { $content = 'REMOTE_ADDR = '.$_SERVER["REMOTE_ADDR"]."\n"; if (isset($_SERVER["HTTP_REFERER"])) { $content .= 'HTTP_REFERER = '.$_SERVER["HTTP_REFERER"]."\n"; } $content .= 'USER_AGENT = '.$_SERVER["HTTP_USER_AGENT"]."\n"; $content .= '$_SERVER[\'REQUEST_URI\'] = '; $content .= var_export(@$_SERVER['REQUEST_URI'], true); $content .= "\n".'$_GET = '; $content .= var_export(@$_GET, true); $content .= "\n".'$_POST = '; $content .= var_export(@$_POST, true); $content .= "\n"; return $content; } /** * Метод отсылает сообщение о ошибки на почту администратору * * @return * @param object $message */ function adminmail($message) { $CI =& get_instance(); // Если конфиг не загружен - загружаем if (!isset($CI->config)) { $CI->config = & load_class('Config'); } // Если загрузчик не загружен - загружаем if (!isset($CI->load)) { $CI->load = & load_class('Loader'); } // Загружаем класс email if (!isset($CI->email)) { $CI->email = & load_class('Email'); } // Для почтового класса необходим класс Language if (!isset($CI->lang)) { $CI->lang = & load_class('Language'); } // Почтовый адрес администратора $email = $CI->config->item('log_to_email'); // Если адрес не указан - ничего не делаем if (!strlen($email)) { return; } // Отсылаем $CI->email->from('noreply'); $CI->email->to($email); $CI->email->subject('Возникла ошибка на сайте'); $CI->email->message($message); $CI->email->send(); } }
Не забывайте. что для включения механизма ведения логов необходимо в файле /system/application/config/config.php указать у параметра log_threshold значением '1'.
Вы можете скачать исходники (Файлы CodeIgniter.php и Common.php от CodeIgniter 1.7.2)
Код довольно простой — думаю что все ясно по исходникам.
Если все таки вопросы возникнут — с удовольствием отвечу в комментариях.
UPDATE: Добавление обработчика исключений с помощью хуков
В комментариях Mordred посоветовал использовать хуки вместо того чтобы править файлы ядра для вызова кода установки обработчика исключений и самого обработчика — спасибо за совет, я так и поступил.
Для начала надо включить механизм куков, для этого в файле /system/application/config/config.php параметр enable_hooks устанавливаем в TRUE:
$config['enable_hooks'] = TRUE;
Затем устанавливаем сам хук в файле /system/application/config/hooks.php пишем:
$hook['pre_system'] = array( 'class' => '', 'function' => 'addExceptionHandler', 'filename' => 'exception_hook.php', 'filepath' => 'hooks' );
Данный код означает что при старте системы будет вызыван метод addExceptionHandler из файла /system/application/hooks/exception_hook.php. Вот содержимое этого файла:
if (! defined('BASEPATH')) exit('No direct script access allowed'); /** * Установка обработчика исключений * */ function addExceptionHandler() { set_exception_handler('_exception_handler2'); } /** * Обработчик исключений * */ function _exception_handler2($errstr) { $error =& load_class('Exceptions'); $error->adminmail('1'); // Выводим текст об исключении на экран echo $error->show_error('error', nl2br($errstr)); // Should we log the error? No? We're done... $config =& get_config(); if ($config['log_threshold'] == 0) { return; } // Пишем сообщение в лог $error->log_exception('Exception', $errstr, '', ''); exit; }
В итоге файлы ядра фреймворка остаются нетронутыми.
Скачать новые исходники можно здесь.
Заодно были сделаны небольшие доработки — если ошибка возникала до загрузки контроллера — не срабатывала отсылка уведомлений админу, так как нужные классы для этого загружены не были, теперь стоит проверка и если нужный класс не загружен, то загружаем тогда его, плюс правки по мелочи.
Оригинал статьи