Фронт-контроллер
Обзор
Zend_Controller_Front реализует
» паттерн
Front Controller, используемый в приложениях » MVC.
Его назначение состоит в инициализации окружения запроса, проложении
маршрута приходящего запроса и последующем запуске выявленных
действий. Он агрегирует все ответы и возвращает их по завершении
процесса.
Zend_Controller_Front также реализует
» паттерн
Singleton, это означает, что в любое время может быть
доступен только один экземпляр этого класса. Это позволяет ему также
выступать в качестве реестра, в котором хранятся другие объекты,
участвующие в процессе диспетчеризации.
Zend_Controller_Front регистрирует в себе брокер плагинов (plugin
broker), что позволяет с помощью плагинов отслеживать события,
инициируемые фронт-контроллером.
В большинстве случаев это дает возможность подгонять
процесс диспетчеризации под конкретный сайт без расширения
фронт-контроллера для добавления функциональности.
Фронт-контроллеру для его работы необходим, как минимум,
один или более путей к директориям, содержащим
контроллеры действий.
Можно также использовать различные методы для дальнейшей
настройки конфигураций фронт-контроллера и его помощников.
Note: Поведение по умолчанию
По умолчанию фронт-контроллер загружает плагин ErrorHandler
и помощник действий ViewRenderer.
Это сделано для упрощения обработки ошибок и рендеринга видов в
контроллерах, соответственно.
Для того, чтобы отключить ErrorHandler , произведите
следующее до вызова метода dispatch() :
// Отключение плагина ErrorHandler:
$front->setParam('noErrorHandler', true);
Для того, чтобы отключить ViewRenderer , сделайте
следующее до вызова метода dispatch() :
// Отключение помощника ViewRenderer:
$front->setParam('noViewRenderer', true);
Ключевые методы
Фронт-контроллер имеет несколько аксессоров для настройки его
конфигурации. Тем не менее, он имеет несколько ключевых в
его функционале методов.
getInstance()
getInstance() используется для получения экземпляра
фронт-контроллера. Поскольку фронт-контроллер реализует паттерн
Singleton, то это также единственно доступный способ
инстанцирования объекта фронт-контроллера.
$front = Zend_Controller_Front::getInstance();
setControllerDirectory() и addControllerDirectory()
setControllerDirectory() используется для того,
чтобы указать диспетчеру, где
искать файлы классов контроллеров действий.
Он принимает один путь или ассоциативный массив пар
модуль => путь в качестве параметра.
Примеры:
// Установка директории контроллеров, используемой по умолчанию:
$front->setControllerDirectory('../application/controllers');
// Одновременная установка нескольких директорий модулей:
$front-> setControllerDirectory(array(
'default' => '../application/controllers',
'blog' => '../modules/blog/controllers',
'news' => '../modules/news/controllers',
));
// Добавление директории модуля 'foo':
$front->addControllerDirectory('../modules/foo/controllers', 'foo');
Note:
Если вы используете addControllerDirectory()
без имени модуля, то он установит директорию для модуля
default . Если директория уже существует, то она
будет перезаписана.
Можно получить текущие установки для директорий
контроллеров, используя метод
getControllerDirectory() . Он вернет массив пар
модуль => директория.
addModuleDirectory() и getModuleDirectory()
Одной из возможностей фронт-контроллера является то, что вы
можете определять модульную
структуру директорий для создания отдельных компонент,
которые называются "модулями".
Каждый модуль должен находиться в собственной директории и
отражать структуру директорий используемого по умолчанию
модуля - т.е., он должен содержать, как минимум, поддиректорию
"controllers"; с ней, как правило, присутствует поддиректория
"views" и другие поддиректории приложения.
Метод addModuleDirectory() позволяет передавать имя
директории, содержащей один или более директорий модулей.
Он их сканирует и добавляет в качестве директорий контроллеров
во фронт-контроллер.
Если вы хотите получить путь к определенному модулю или к
текущему модулю, то можете использовать метод
getModuleDirectory() , при передаче имени модуля он
возвращает путь к нему, иначе возвращается путь к текущему
модулю.
dispatch()
dispatch(Zend_Controller_Request_Abstract $request = null,
Zend_Controller_Response_Abstract $response = null)
является "рабочей лошадкой" фронт-контроллера. Он может
опционально принимать
объект
запроса и/или
объект
ответа, что дает разработчикам возможность передавать
свои объекты.
Если методу dispatch() не были переданы объект
запроса или ответа, то он будет проверять, были ли ранее
зарегистрированы объекты, и использовать их, либо инстанцировать
версии по умолчанию (в обоих случаях по умолчанию будут
использоваться разновидность HTTP).
Аналогичным образом dispatch() производит проверку
на уже зарегистрированные объекты
маршрутизатора и
диспетчера, и
если они не найдены, то инстанцирует версии по умолчанию.
Процесс диспетчеризации имеет три отдельных события:
Маршрутизация
Диспетчеризация
Ответ
Маршрутизация производится только один раз, когда вызывается
dispatch() , при этом используются значения в
объекте запроса. Диспетчеризация производится циклически. Запрос
может означать вызов нескольких действий, контроллер или плагин
могут сбрасывать объект запроса для дополнительного вызова
других действий. Когда все действия выполнены, фронт-контроллер
возвращает ответ.
run()
Zend_Controller_Front::run($path) - статический
метод, принимающий только путь к директории контроллеров. Он
извлекает экземпляр фронт-контроллера через
getInstance()),
регистрирует этот путь через
setControllerDirectory(), и в конце вызывает метод dispatch().
В сущности, run() представляет собой удобный
метод, который можно использовать при разработке сайта, не
требующего специальной настройки фронт-контроллера.
// Инстанцирование фронт-контроллера, установка директории контроллера и
// выполнение диспетчеризации в одном вызове:
Zend_Controller_Front::run('../application/controllers');
Методы-аксессоры для конфигурирования
Кроме методов, перечисленных выше, есть методы-аксессоры, которые
можно использовать для управления конфигурацией фронт-контроллера -
и одновременно конфигурацией классов, которым фронт-контроллер
делегирует выполнение.
-
resetInstance() может использоваться для сброса
всех текущих настроек. Он в основном предназначен для
тестирования, но может также использоваться в тех случаях,
когда нужно связать между собой несколько
фронт-контроллеров.
-
(set|get)DefaultControllerName() позволяют
установить другое имя используемого
по умолчанию контроллера (иначе используется 'index') и
получить текущее значение. Они служат посредниками к
диспетчеру.
-
(set|get)DefaultAction() позволяют
установить другое имя используемого по умолчанию действия
(иначе используется 'index') и получить текущее
значение. Они служат посредниками к
диспетчеру.
-
(set|get)Request() позволяют установить
класс запроса
или его объект для использования в процессе диспетчеризации
и получить текущий объект. При установке объекта
запроса вы можете передать имя класса запроса, в этом случае
метод загрузит файл класса и инстанцирует его.
-
(set|get)Router() позволяют установить
класс
маршрутизатора
или его объект, используемые в течение процесса
диспетчеризации, и получить текущий объект. Когда
устанавливается объект маршрутизатора, вы можете передать
имя класса маршрутизатора, в этом случае метод загрузит файл
класса и инстанцирует его.
При извлечении объекта маршрутизатора сначала производится
проверка, представлен ли во фронт-контроллере такой объект и
в случае его отсутствия инстанцирует используемый по
умолчанию маршрутизатор (Rewrite Router).
-
(set|get)BaseUrl() дают возможность установить
базовый
URL, который удаляется из начала при
маршрутизации запросов, и получить его текущее значение.
Это значение передается объекту запроса непосредственно до
маршрутизации.
-
(set|get)Dispatcher() дают возможность
установки класса
диспетчера
или его объекта для использования в течение диспетчеризации,
и получения текущего объекта. При установке объекта
диспетчера можно передать имя класса диспетчера, в этом
случае метод загрузит файл класса и инстанцирует его.
При извлечении объекта диспетчера, метод сначала производит
проверку того, представлен ли во фронт-контроллере такой
объект и в случае его отсутствия инстанцирует диспетчер,
используемый по умолчанию.
-
(set|get)Response() дают возможность установить
класс ответа
или его объект для использования в процессе диспетчеризации,
и извлечь текущий объект. При установке объекта
ответа можно передать имя класса ответа, в этом случае метод
загрузит файл класса и инстанцирует его.
-
registerPlugin(Zend_Controller_Plugin_Abstract $plugin, $stackIndex = null)
позволяет регистрировать объекты плагинов.
Путем установки опционального параметра
$stackIndex, вы можете
контролировать порядок, в котором выполняются плагины.
-
unregisterPlugin($plugin) позволяет отменять
регистрацию объектов плагинов.
$plugin может быть как объектом плагина, так и строкой, обозначающей класс плагина, регистрацию которого надо отменить.
-
throwExceptions($flag) используется для
включения/отключения возможности генерации исключений в
течение процесса диспетчеризации. По умолчанию исключения
отлавливаются и размещаются в
объекте
ответа; включение throwExceptions()
переопределит это поведение
Более полробную информацию читайте в Исключения.
-
returnResponse($flag) используется для того,
чтобы указать фронт-контроллеру - возвращать ли ответ
из dispatch() (TRUE), либо ответ
должен быть отправлен автоматически (FALSE). По
умолчанию ответ отправляется автоматически
(через вызов
Zend_Controller_Response_Abstract::sendResponse() );
включение returnResponse() переопределит это
поведение.
Ситуации, в которых может потребоваться возврат ответа,
включают в себя проверку на предмет исключений до отправки
ответа клиенту, необходимость журналирования различных
аспектов ответа (таких, как заголовки) и т.д.
Параметры фронт-контроллера
Во введении мы указали на то, что фронт-контроллер также выступает
как реестр для различных компонент контроллера. Это реализуется
через группу методов для параметров. Эти методы позволяют
регистрировать произвольные данные - объекты и переменные - во
фронт-контроллере, чтобы их можно было извлечь в любой точке цепочки
диспетчеризации. Эти значения передаются маршрутизатору, диспетчеру,
и контроллерам действий. Эти методы включают в себя:
-
setParam($name, $value) дает возможность
установить единственный параметр с именем $name
и значением $value.
-
setParams(array $params) позволяет
установить несколько параметров одновременно с помощью
ассоциативного массива.
-
getParam($name) дает возможность извлечь один
параметр за один раз, используя его имя $name в
качестве идентификатора.
-
getParams() позволяет извлечь все
параметры за один раз.
-
clearParams() позволяет удалить один параметр
(путем передачи строкового идентификатора), нескольких
параметров (путем передачи массива строковых
идентификаторов) или весь стек параметров (без передачи
чего-либо).
Есть несколько предопределенных параметров специально для
использования в цепочке диспетчеризации:
-
useDefaultControllerAlways используется для
указания
диспетчеру,
что следует использовать контроллер по умолчанию в модуле
по умолчанию для любых запросов, диспетчеризация которых
невозможна (т.е. модуль, контроллер и/или действие не
существуют). По умолчанию он отключен.
См. Исключения в MVC, с которыми вы можете встретиться за
более подробной информацией об использовании этого параметра
настройки.
-
disableOutputBuffering используется для
указания
диспетчеру,
что не следует использовать буферизацию вывода для сбора
данных на вывод, генерируемых контроллерами действий. По
умолчанию диспетчер собирает весь вывод и присоединяет его к
телу содержимого в объекте ответа.
-
noViewRenderer используется для отключения
помощника ViewRenderer.
Установите этот параметр в true для его отключения.
-
noErrorHandler используется для отключения
плагина
Error Handler
Установите этот параметр в true для его отключения.
Расширение фронт-контроллера
При наследовании от фронт-контроллера, необходимо, как
минимум, переопределить метод getInstance() .
class My_Controller_Front extends Zend_Controller_Front
{
public static function getInstance ()
{
if (null === self::$_instance) {
self::$_instance = new self();
}
return self::$_instance;
}
}
Такое переопределение метода getInstance() гарантирует
то, что последующий вызов
Zend_Controller_Front::getInstance() вернет экземпляр
созданного вами подкласса вместо экземпляра
Zend_Controller_Front - это особенно полезно
для некоторых альтернативных маршрутизаторов и помощников видов.
Как правило, нет необходимости создавать подклассы
фронт-контроллера, если только не нужно добавить новый
функционал (например, автозагрузку плагинов или способ
определения путей к помощникам действий). Целями, для достижения
которых может потребоваться изменение поведения фронт-контроллера,
могут быть изменение принципа хранения директорий
контроллеров, установка других используемых по умолчанию
маршрутизатора и диспетчера и т.д.
|
|