Продолжаю серию постов о Zend Framework.
В моем проекте передо мной встала задача. Мне нужно было сделать меню администратора, которое бы появлялось на странице при определенных событиях (например, после аутентификации).
Сначала я хотел решить эту задачу, определив базовый контроллер для всех контроллеров моего проекта. Но, я подумал, что это не лучший способ решения задачи, потому как я нашел более привлекательный метод - использовать плагин для фронт-контроллера. Такое решение мне показалось лучшим потому, что мы получаем менее связанный код. Чтобы убрать меню - нам придется всего лишь отключить плагин фронт-контроллера - это все. Нас опять выручают плагины!
Нам понадобится написать код плагина. Далее, я расскажу, как он работает. Итак, код:
class Project_Controller_Plugin_Toolbar extends Zend_Controller_Plugin_Abstract
{
public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
{
if (!$request->isXmlHttpRequest()) {
$actionStack = Zend_Controller_Front::getInstance()
->getPlugin('Zend_Controller_Plugin_ActionStack');
$menuAction = clone $request;
$menuAction->setModuleName('application')
->setActionName('index')
->setControllerName('toolbar');
$actionStack->pushStack($menuAction);
}
}
}
Теперь прокомментирую код.
Этот плагин срабатывает перед запуском цикла диспетчеризации, это обеспечивается определением метода dispatchLoopStartup(), в который передается объект текущего запроса. Видно, что логика метода завернуто в условие, которое определяет, что код не должен выполняться для AJAX запросов - нам же не нужно кашу к примеру, из JSON и нашего меню? :)
Дальше мы получаем стек плагин, управляющий стеком действий. Затем клонируем объект текущего запроса и устанавливаем при помощи аксессоров объекта свои значения контроллера, действия и модуля (так как мой проект имеет модульную структуру контроллеров).
В конце метода мы кладем в стек наш клонированный и настроенный объект запроса.
Итак, что получилось? Получилось, что мы создали новый объект запроса путем клонирования, которому установили значения модуля, контроллера и действия, а затем поместили его в стек действий. Плагин Zend_Controller_Plugin_ActionStack последовательно производит диспетчеризацию запросов из стека, после диспетчеризации основного действия (плагин делает это в хуке postDispatch()).
Важно! Не забудьте подключить к фронт-контроллеру плагин Zend_Controller_Plugin_ActionStack обслуживающий стек действий. Без него наш плагин Project_Controller_Plugin_Toolbar работать не будет.
$front->registerPlugin(new Zend_Controller_Plugin_ActionStack(), 97);
И, конечно, не забываем подключить и наш свеженаписанный плагин:
$front->registerPlugin(new Tanraya_Controller_Plugin_Toolbar(), 111);
А что же происходит в нашем контроллере ToolbarController? Там все просто - в методе indexAction() мы указываем, в какой сегмент макета выводить отрендеренный шаблон вида:
$this->_helper->viewRenderer->setResponseSegment('toolbar');
А в макете вывод сегмента выглядит так:
<?=$this->layout()->toolbar ?>
Ну вот - наше меню готово. У меня появились мысли, сделать универсальный механизм для работы с блоками, чтобы не писать отдельных плагинов для каждого блока на сайте. Я имею в виду те блоки, которые не кочуют из проекта в проект, как меню администратора, а используются только на конкретном сайте. Я пока не придумал, как реализовать такой механизм красиво, но зачатки мыслей уже есть и их нужно еще раз обдумать и реализовать. Как сделаю - напишу об этом отдельный пост.
Всем спасибо за внимание :)
Also interesting
Tags: plugins, zend framework, zf front controller plugin, zf layout
Огромное спасибо! Очень помогла ваша информация!!!)))))))))))
А чем Zend_Navigation не таков?