Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- вывелось такое
- Перехвачена ошибка!
- E_USER_ERROR: Damn it! in /var/www/php.xxx/except/w2e_hier.php:9
- Stack trace:
- #0 [internal function]: PHP_Exceptionizer_Catcher->handler(256, 'Damn it!', '/var/www/php.xx...', 9, Array)
- #1 /var/www/php.xxx/except/w2e_hier.php(9): trigger_error('Damn it!', 256)
- #2 /var/www/php.xxx/except/w2e_hier.php(3): suffer()
- #3 {main}
- Листинг 26.20. Преобразование ошибок в исключения. Файл w2e_simple.php
- <?php ## Иерархия ошибок.
- require_once "PHP/Exceptionizer.php";
- suffer();
- function suffer()
- {
- $w2e = new PHP_Exceptionizer(E_ALL);
- try {
- // Генерируем ошибку.
- trigger_error("Damn it!", E_USER_ERROR);
- } catch (AboveE_USER_WARNING $e) {
- // Перехват ошибок: E_USER_WARNING и более серьезных.
- echo "<pre><b>Перехвачена ошибка!</b>\n", $e, "</pre>";
- }
- }
- ?>
- Exceptionizer.php
- <?php ## Класс для преобразования ошибок PHP в исключения.
- /**
- * Класс для преобразования перехватываемых (см. set_error_handler())
- * ошибок и предупреждений PHP в исключения.
- *
- * Следующие типы ошибок, хотя и поддерживаются формально, не могут
- * быть перехвачены:
- * E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR,
- * E_COMPILE_WARNING
- */
- class PHP_Exceptionizer
- {
- // Создает новый объект-перехватчик и подключает его к стеку
- // обработчиков ошибок PHP (используется идеология "выделение
- // ресурса есть инициализация").
- public function __construct($mask = E_ALL, $ignoreOther = false)
- {
- $catcher = new PHP_Exceptionizer_Catcher();
- $catcher->mask = $mask;
- $catcher->ignoreOther = $ignoreOther;
- $catcher->prevHdl = set_error_handler(array($catcher, "handler"));
- }
- // Вызывается при уничтожении объекта-перехватчика (например,
- // при выходе его из области видимости функции). Восстанавливает
- // предыдущий обработчик ошибок.
- public function __destruct()
- {
- restore_error_handler();
- }
- }
- /**
- * Внутренний класс, содержащий метод перехвата ошибок.
- * Мы не можем использовать для этой же цели непосредственно $this
- * (класса PHP_Exceptionizer): вызов set_error_handler() увеличивает
- * счетчик ссылок на объект, а он должен остаться неизменным, чтобы в
- * программе всегда оставалась ровно одна ссылка.
- */
- class PHP_Exceptionizer_Catcher
- {
- // Битовые флаги предупреждений, которые будут перехватываться.
- public $mask = E_ALL;
- // Признак, нужно ли игнорировать остальные типы ошибок, или же
- // следует использовать стандартный механизм обработки PHP.
- public $ignoreOther = false;
- // Предыдущий обработчик ошибок.
- public $prevHdl = null;
- // Функция-обработчик ошибок PHP.
- public function handler($errno, $errstr, $errfile, $errline)
- {
- // Если error_reporting нулевой, значит, использован оператор @,
- // и все ошибки должны игнорироваться.
- if (!error_reporting()) return;
- // Перехватчик НЕ должен обрабатывать этот тип ошибки?
- if (!($errno & $this->mask)) {
- // Если ошибку НЕ следует игнорировать...
- if (!$this->ignoreOther) {
- if ($this->prevHdl) {
- // Если предыдущий обработчик существует, вызываем его.
- $args = func_get_args();
- call_user_func_array($this->prevHdl, $args);
- } else {
- // Иначе возвращаем false, что вызывает запуск встроенного
- // обработчика PHP.
- return false;
- }
- }
- // Возвращаем true (все сделано).
- return true;
- }
- // Получаем текстовое представление типа ошибки.
- $types = array(
- "E_ERROR", "E_WARNING", "E_PARSE", "E_NOTICE", "E_CORE_ERROR",
- "E_CORE_WARNING", "E_COMPILE_ERROR", "E_COMPILE_WARNING",
- "E_USER_ERROR", "E_USER_WARNING", "E_USER_NOTICE", "E_STRICT",
- );
- // Формируем имя класса-исключения в зависимости от типа ошибки.
- $className = __CLASS__ . "_" . "Exception";
- foreach ($types as $t) {
- $e = constant($t);
- if ($errno & $e) {
- $className = $t;
- break;
- }
- }
- // Генерируем исключение нужного типа.
- throw new $className($errno, $errstr, $errfile, $errline);
- }
- }
- /**
- * Базовый класс для всех исключений, полученных в результате ошибки PHP.
- */
- abstract class PHP_Exceptionizer_Exception extends Exception
- {
- public function __construct($no = 0, $str = null, $file = null, $line = 0) {
- parent::__construct($str, $no);
- $this->file = $file;
- $this->line = $line;
- }
- }
- /**
- * Создаем иерархию "серьезности" ошибок, чтобы можно было
- * ловить не только исключения с указанием точного типа, но
- * и сообщения, не менее "фатальные", чем указано.
- */
- class E_EXCEPTION extends PHP_Exceptionizer_Exception {}
- class AboveE_STRICT extends E_EXCEPTION {}
- class E_STRICT extends AboveE_STRICT {}
- class AboveE_NOTICE extends AboveE_STRICT {}
- class E_NOTICE extends AboveE_NOTICE {}
- class AboveE_WARNING extends AboveE_NOTICE {}
- class E_WARNING extends AboveE_WARNING {}
- class AboveE_PARSE extends AboveE_WARNING {}
- class E_PARSE extends AboveE_PARSE {}
- class AboveE_ERROR extends AboveE_PARSE {}
- class E_ERROR extends AboveE_ERROR {}
- class E_CORE_ERROR extends AboveE_ERROR {}
- class E_CORE_WARNING extends AboveE_ERROR {}
- class E_COMPILE_ERROR extends AboveE_ERROR {}
- class E_COMPILE_WARNING extends AboveE_ERROR {}
- class AboveE_USER_NOTICE extends E_EXCEPTION {}
- class E_USER_NOTICE extends AboveE_USER_NOTICE {}
- class AboveE_USER_WARNING extends AboveE_USER_NOTICE {}
- class E_USER_WARNING extends AboveE_USER_WARNING {}
- class AboveE_USER_ERROR extends AboveE_USER_WARNING {}
- class E_USER_ERROR extends AboveE_USER_ERROR {}
- // Иерархии пользовательских и встроенных ошибок не сравнимы,
- // т.к. они используются для разных целей, и оценить
- // "серьезность" нельзя.
- ?>
Advertisement
Add Comment
Please, Sign In to add comment