Система Zend_Controller
построена с расчетом на
расширение посредством либо создания подклассов от существующих,
либо написания новых классов, которые реализуют интерфейсы
Zend_Controller_Router_Interface
и
Zend_Controller_Dispatcher_Interface
.
Возможными причинами для реализации нового маршрутизатора или диспетчера могут быть:
Существующая система маршрутизации URI не подходит в некоторых сиуациях, таких, как интеграция в существующий веб-сайт, который использует свои собственные соглашения для марршрутизации, которые не совместимы с механизмом маршрутизации, предоставляемым Zend Framework.
Вам нужно реализовать маршрутизацию для чего-либо совершенно
иного. Класс Zend_Controller_Router
работает только с URI. Возможно, вы захотите
использовать паттерн MVC для разработки других типов
программ -- таких, как консольное приложение. В случае
консольного приложения специализированный маршрутизатор
может обрабатывать аргументы в командной строке для
определения маршрута.
Механизм, предоставляемый Zend_Controller_Dispatcher
является неподходящим. Конфигурация по умолчанию
предполагает, что контроллеры являются классами, а действия --
методами этих классов. Однако есть много других стратегий
для реализации этого. Примером такой стратегии может быть
та, где контроллеры являются каталогами, а действия --
файлами внутри этих каталогов.
Вы хотите обеспечить дополнительные возможности, которые
будут унаследованы всеми вашими контроллерами. Например,
Zend_Controller_Action
по умолчанию не
интегрирован с Zend_View
. Однако вы можете
расширить свой собственный контроллер для реализации этого,
и его использование не потребует изменения находящегося
в поставке Zend_Controller_Router
или
Zend_Controller_Dispatcher
Пожалуйста, будьте осторожны при переписывании важных частей системы,
особенно диспетчера. Одним из преимуществ Zend_Controller
является то, что он устанавливает общие соглашения для
разрабатываемых приложений. Если изменено слишком многое из поведения
по умолчанию, нетоторые из этих преимуществ будут потеряны. Тем не
менее, есть много разных потребностей, и одно решение не может
соответствовать им всем, поэтому некоторая свобода допустима, если нужно.
Сильно приветствуется следование данным соглашениям в наименовании
и хранении файлов при создании подклассов любых классов
Zend_Controller
. Выполнение этого будет гарантировать
легкое понимание вашего проекта другим программистом, знакомым
с Zend Framework.
Классы, входящие в Zend Framework, следуют соглашению, по которому имя каждого класса начинается с "Zend_". Это префикс. Мы рекомендуем называть все свои классы аналогичным образом, т.е. если ваша компания называется Widget Inc., "Widget_" должен быть префиксом.
Классы Zend_Controller
хранятся в каталоге библиотек,
как приведено ниже:
/library /Zend /Controller Action.php Dispatcher.php Router.php
Когда создаете наследников от классов Zend_Controller
,
то рекомендуется сохранять их в такой же структуре под вашим префиксом.
Например, проект компании Widget Inc., который реализует только свой маршрутизатор, может выглядеть следующим образом:
/library /Zend /Widget /Controller Router.php README.txt
Обратите внимание, что в этом примере каталог
Widget/Controller/
копирует каталог
Zend/Controller/
везде, где это возможно. В данном
случае это класс Widget_Controller_Router
, который
может быть либо подклассом Zend_Controller_Router
,
либо замещать его, реализуя интерфейс
Zend_Controller_Router_Interface
.
Еще обратите внимание на то, что в вышеприведенном примере в
каталоге Widget/Controller/
размещен файл
README.txt
. Zend сильно приветствует документирование
проектов посредством отдельных тестов и документации для клиентов.
Несмотря на это, рекомендуется еще размещать простой файл
README.txt
, в котором кратко описываются изменения
и как они работают.
Интерфейс Zend_Controller_Router_Interface
дает определение
только одному методу:
<?php /** * @param Zend_Controller_Dispatcher_Interface * @throws Zend_Controller_Router_Exception * @return Zend_Controller_Dispatcher_Token|boolean */ public function route(Zend_Controller_Dispatcher_Interface $dispatcher); ?>
Маршрутизация производится только один раз: когда запрос впервые
получен системой. Целью маршрутизатора является генерация маркера
Zend_Controller_Dispatch_Token
, который
определяет контроллер и действие в этом контроллере. Далее маркер
передается диспетчеру. Если невозможно преобразовать маршрут в
маркер диспетчеризации, то возвращается булево значение FALSE
.
Некоторые маршрутизаторы могут обрабатывать динамические элементы и
нуждаются в способе проверки того, является ли сгенерированный
маркер возможным для диспетчеризации в настоящее время, до его возвращения.
Поэтому маршрутизатор принимает объект диспетчера как единственный
аргумент его метода route()
. Объект диспетчера
предоставляет метод isDispatchable()
для этой проверки.
Zend_Controller_Front
сначала будет вызывать
маршрутизатор для получения первого маркера
диспетчеризации, который он передаст диспетчеру. Диспетчер будет
вызывать действие (создавая экземпляр контроллера) и после
возвращать либо булево значение FALSE
, либо другой
маркер диспетчеризации.
Zend_Controller_Front
повторно вызывает диспетчер,
пока он возвращает маркер диспетчеризации. Это известно как цикл
диспетчеризации. Он позволяет обрабатывать действия до тех пор,
пока не будет выполнена вся работа.
Интерфейс Zend_Controller_Dispatcher_Interface
дает
определение двум методам:
<?php /** * @param Zend_Controller_Dispatcher_Token $route * @return boolean */ public function isDispatchable(Zend_Controller_Dispatcher_Token $route); ?>
isDispatchable()
проверяет, является ли маркер возможным
для диспетчеризации. Если является, то возвращается TRUE
,
иначе FALSE
. Определение того, что возможно для
диспетчеризации, зависит от класса, реализующего интерфейс. В
случае реализации по умолчанию (Zend_Controller_Dispatcher
)
это означает, что файл контроллера существует, класс существует
в этом файле и метод, реализующий действие, существует в этом классе.
<?php /** * @param Zend_Controller_Dispatcher_Token $route * @return Zend_Controller_Dispatcher_Token|boolean */ public function dispatch(Zend_Controller_Dispatcher_Token $route); ?>
dispatch()
является рабочим методом. Этот метод должен
выполнять действие контроллера. Он должен возвращать либо маркер
диспетчеризации, либо FALSE
, который указывает, что
работа выполнена.