# Zend_Controller_Plugins_ErrorHandler

`Zend_Controller_Plugins_ErrorHandler` представляет собой плагин для обработки исключений, брошенных вашим приложением, включая те, которые вызваны отсутствием запрошенного контроллера или действия. Он является альтернативой способам, перечисленным в разделе об исключениях MVC.

Основные назначения этого плагина:

- Перехват исключений, вызванных отсутствием контроллера или метода действия

- Перехват исключений, брошенных в контроллерах действий

Другими словами, плагин ErrorHandler спроектирован для обработки HTTP-ошибок типа 404 (отсутствует страница) и 500 (внутренняя ошибка). Он не предназначен для отлова исключений, сгенерированных в других плагинах или в процессе маршрутизации.

По умолчанию `Zend_Controller_Plugins_ErrorHandler` будет производить переход к `ErrorController::errorAction()` в модуле по умолчанию. Вы можете установить альтернативные значения для перехода, используя набор методов-аксессоров, доступных в плагине:

- `setErrorHandlerModule()` устанавливает модуль, на который производится переход.

- `setErrorHandlerController()` устанавливает контроллер, на который производится переход.

- `setErrorHandlerAction()` устанавливает действие, на которое производится переход.

- `setErrorHandler()` принимает ассоциативный массив, который может содержать любые из ключей 'module', 'controller' или 'action'.

Кроме этого, вы можете опционально передать конструктору ассоциативный массив, который будет в свою очередь передан `setErrorHandler()`.

`Zend_Controller_Plugin_ErrorHandler` регистрирует перехватчик `postDispatch()` и проверяет, есть ли зарегистрированые исключения в объекте ответа. Если есть, то производится попытка перехода на действие, зарегистрированное в качестве обработчика ошибок.

Если во время диспетчеризации обработчика ошибок произошло исключение, то плагин скажет фронт-контроллеру, чтобы тот бросил исключения, и повторно бросит последнее исключение, зарегистрированное в объекте ответа.

## Использование ErrorHandler в качестве обработчика ошибки 404

Поскольку плагин захватывает не только ошибки приложения, но и ошибки в цепочке контроллеров, вызванные отсутствием класса контроллера и/или метода действия, то он может использоваться в качестве обработчика ошибки 404. В этом случае нужно, чтобы ваш контроллер ошибок проверял тип исключения.

Перехваченные исключения журналируются в объекте, зарегистрированном в запросе. Для его получения используйте метод `Zend_Controller_Action::_getParam('error_handler')`:

    class ErrorController extends Zend_Controller_Action
    {
        public function errorAction()
        {
            $errors = $this->_getParam('error_handler');
        }
    }

Имея объект ошибки, вы можете получить тип ошибки через `$errors->type`. Тип ошибки может быть одним из следующих:

- `Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER`, означает, что контроллер не был найден.

- `Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION`, означает, что запрошенное действие не было найдено.

- `Zend_Controller_Plugin_ErrorHandler::EXCEPTION_OTHER`, обозначает другие исключения.

Вы можете производить проверку на первые два типа и в случае положительного ответа указывать страницу 404:

    class ErrorController extends Zend_Controller_Action
    {
        public function errorAction()
        {
            $errors = $this->_getParam('error_handler');

            switch ($errors->type) {
                case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
                case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
                    // ошибка 404 - не найден контроллер или действие
                    $this->getResponse()
                         ->setRawHeader('HTTP/1.1 404 Not Found');

                    // ... получение данных для отображения...
                    break;
                default:
                    // ошибка приложения; выводим страницу ошибки,
                    // но не меняем код статуса
                    break;
            }
        }
    }

Вы можете извлекать исключение, которое инициировало вызов обработчика ошибок, через свойство `exception` объекта `error_handler`:

    public function errorAction()
    {
            $errors = $this->_getParam('error_handler');

            switch ($errors->type) {
                case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
                case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
                    // ошибка 404 - не найден контроллер или действие
                    $this->getResponse()
                         ->setRawHeader('HTTP/1.1 404 Not Found');

                    // ... получение данных для отображения...
                    break;
                default:
                    // ошибка приложения; выводим страницу ошибки,
                    // но не меняем код статуса

                    // ...

                    // Журналируем исключение:
                    $exception = $errors->exception;
                    $log = new Zend_Log(
                        new Zend_Log_Writer_Stream(
                            '/tmp/applicationException.log'
                        )
                    );
                    $log->debug($exception->getMessage() . "\n" .
                                $exception->getTraceAsString());
                    break;
            }
    }

## Управление сгенерированным ранее выводом

Если в процессе обработки запроса вызывается несколько действий, или ваше действие несколько раз вызывает метод `render()`, то возможно, что объект ответа уже содержит в себе сохраненные данные для вывода. Это может привести к тому, что выведется смесь из ожидаемого содержимого и содержимого ошибки.

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

    $this->getResponse()->clearBody();

## Примеры использования плагина

### Стандартное использование

    $front = Zend_Controller_Front::getInstance();
    $front->registerPlugin(new Zend_Controller_Plugin_ErrorHandler());

### Установка другого обработчика ошибок

    $front = Zend_Controller_Front::getInstance();
    $front->registerPlugin(new Zend_Controller_Plugin_ErrorHandler(array(
        'module'     => 'mystuff',
        'controller' => 'static',
        'action'     => 'error'
    )));

### Использование аксессоров

    $plugin = new Zend_Controller_Plugin_ErrorHandler();
    $plugin->setErrorHandlerModule('mystuff')
           ->setErrorHandlerController('static')
           ->setErrorHandlerAction('error');

    $front = Zend_Controller_Front::getInstance();
    $front->registerPlugin($plugin);

## Пример контроллера ошибок

Для того, чтобы использовать плагин ErrorHandler, нужен контроллер ошибок. Ниже приводится простой пример такого контроллера.

    class ErrorController extends Zend_Controller_Action
    {
        public function errorAction()
        {
            $errors = $this->_getParam('error_handler');

            switch ($errors->type) {
                case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
                case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
                    // ошибка 404 - не найден контроллер или действие
                    $this->getResponse()->setRawHeader('HTTP/1.1 404 Not Found');

                    $content =<<<EOH
    <h1>Ошибка!</h1>
    <p>Запрошенная вами страница не найдена.</p>
    EOH;
                    break;
                default:
                    // ошибка приложения
                    $content =<<<EOH
    <h1>Ошибка!</h1>
    <p>Произошла непредвиденная ошибка. Пожалуйста, попробуйте позднее.</p>
    EOH;
                    break;
            }

            // Удаление добавленного ранее содержимого
            $this->getResponse()->clearBody();

            $this->view->content = $content;
        }
    }