Programmer's Reference Guide

Контроллеры действийAction Controllers

Помощники действий

Введение

Помощники действий (action helpers) позволяют разработчикам добавлять функционал во время выполнения или по требованию в любые контроллеры действий, который расширяет Zend_Controller_Action. Помощники действий помогают снизить необходимость расширения абстрактного контроллера действий для того, чтобы добавить общий функционал в контроллер действий.

Есть несколько вариантов использования помощников действий. Помощники действий используют брокерскую систему (brokerage system), подобную той, которая используется в Zend_View_Helpers и Zend_Controller_Plugin. Помощники действий (как и Zend_View_Helpers) могут быть загружены и вызваны по требованию, либо инстанцироваться во время запроса (начальной загрузки) или создания контроллера действий (init()). Для того, чтобы лучше разобраться с этим, см. раздел использования ниже.

Инициализация помощника

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

Брокер помощников хранится как член $_helper класса Zend_Controller_Action; используйте брокер для получения или вызова помощников. Методы, предназначенные для этого, включают в себя:

  • Явное использование getHelper(). Просто передавайте ему имя, и будет возвращен объект помощника:

    <?php
    $flashMessenger = $this->_helper->getHelper('FlashMessenger');
    $flashMessenger->addMessage('We did something in the last request');
                    
  • Используйте функционал метода __get() брокера помощников и извлекайте помощника так же, как если бы он был свойством этого брокера.

    <?php
    $flashMessenger = $this->_helper->FlashMessenger;
    $flashMessenger->addMessage('We did something in the last request');
                    
  • И наконец, большинство помощников действий реализует метод direct(), который будет вызывать особый, используемый по умолчанию метод в помощнике. Например, в случае FlashMessenger будет вызван метод addMessage():

    <?php
    $this->_helper->FlashMessenger('We did something in the last request');
                    

Замечание: Все примеры выше функционально эквивалентны.

Вы можете также явно инстанцировать помощников. Вы можете захотеть сделать это, если используете помощника вне контроллера действий, или если хотите передавать помощника брокеру для использования в любых действиях. Инстанцирование производится так же, как и для любого другого класса PHP.

Брокер помощников

Zend_Controller_Action_HelperBroker управляет регистрацией объектов помощников и путей к помощникам, а также извлечением помощников по требованию.

Для того, чтобы зарегистрировать помощника через брокер, используйте addHelper:

<?php
Zend_Controller_Action_HelperBroker::addHelper($helper);
        

Конечно, инстанцирование и передача помощников брокеру отнимают некоторое время и ресурсы, поэтому существуют два метода для некоторой автоматизации: addPrefix() и addPath().

  • addPrefix() принимает префикс класса и использует его для определения пути, по которому определен класс помощника. Подразумевается, что префикс следует соглашениям по именованию классов Zend Framework.

    <?php
    // Добавление помощников, начинающихся с My_Action_Helpers в My/Action/Helpers/
    Zend_Controller_Action_HelperBroker::addPrefix('My_Action_Helpers');
                    
  • addPath() принимает директорию в качестве первого аргумента и префикс класса в качестве второго (по умолчанию это 'Zend_Controller_Action_Helper'). Это позволяет вам поставить в соответствие определенным директориям собственные префиксы классов.

    <?php
    // Добавление помощников, начинающихся с Helper в Plugins/Helpers/
    Zend_Controller_Action_HelperBroker::addPath('./Plugins/Helpers', 'Helper');
                    

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

Для определения того, есть ли помощник в брокере, используйте hasHelper($name), где $name - короткое имя помощника (без префикса):

<?php
// Проверка, зарегистрирован ли в брокере помощник 'redirector'
if (Zend_Controller_Action_HelperBroker::hasHelper('redirector')) {
    echo 'Помощник Redirector зарегистрирован';
}
        

Наконец, для удаления зарегистрированного помощника из брокера, используйте removeHelper($name), где $name - короткое имя помощника (без префикса):

<?php
// Удаление помощника 'redirector' из брокера, помещенное в условную конструкцию
if (Zend_Controller_Action_HelperBroker::hasHelper('redirector')) {
    Zend_Controller_Action_HelperBroker::removeHelper('redirector')
}
        

Встроенные помощники действий

Zend Framework по умолчанию включает в себя три помощника действий: FlashMessenger для управления мгновенными сообщениями, Redirector, предоставляющий различные реализации перенаправления на внутренние и внешние страницы из вашего приложения, и ViewRenderer для автоматизации процесса настройки объекта вида в ваших контроллерах и рендеринга видов.

FlashMessenger

Введение

Помощник FlashMessenger позволяет передавать сообщения, которые нужно показать пользователю при следующем запросе. Для хранения сообщений до следующего запроса FlashMessenger использует Zend_Session_Namespace . Как правило, лучше всего использовать тот Zend_Session или Zend_Session_Namespace, который вы инициализировали с помощью Zend_Session::start() в файле загрузки. (За более подробной информацией об использовании см. Zend Session).

Базовый пример использования

Пример использования ниже демонстрирует самые основы использования мессенджера. Когда вызывается действие /some/my, оно добавляет мгновенное сообщение "Record Saved!". Последующий запрос к действию /some/my-next-request получит это сообщение (и удалит его).

<?php
class SomeController extends Zend_Controller_Action
{
    /**
     * FlashMessenger
     *
     * @var Zend_Controller_Action_Helper_FlashMessenger
     */
    protected $_flashMessenger = null;
    
    public function init()
    {
        $this->_flashMessenger = $this->_helper->getHelper('FlashMessenger');
        $this->initView();
    }
    
    public function myAction()
    {
        /**
         * default method of getting Zend_Controller_Action_Helper_FlashMessenger
         * instance on-demand
         */
        $this->_flashMessenger->addMessage('Record Saved!');
    }

    public function myNextRequestAction()
    {
        $this->view->messages = $this->_flashMessenger->getMessages();
        $this->render();
    }
}
        

Redirector

Введение

Помощник Redirector позволяет использовать объект redirector для удовлетворения нужд приложения в перенаправлении на новые URL. Он дает многие преимущества по сравнению с методом _redirect(), такие, как возможность предварительной конфигурации поведения на стороне сайта в объекте redirector или использование встроенного интерфейса goto($action, $controller, $module, $params), подобного интерфейсу Zend_Controller_Action::_forward().

Redirector имеет набор методов, которые могут использоваться для воздействия на поведение при перенаправлении:

  • setCode() может использоваться для установки кода ответа HTTP, используемого при перенаправлении.

  • setExit() может использоваться для установки принудительного вызова exit() после перенаправления. По умолчанию он установлен в true.

  • setGoto() может использоваться для установки URL, используемого по умолчанию (когда методу goto() не был передан URL). Использует интерфейс Zend_Controller_Action::_forward(): setgoto($action, $controller = null, $module = null, array $params = array());

  • setGotoRoute() может использоваться для установки URL, основываясь на зарегистрированном маршруте. Передавайте массив пар ключ/значение и имя маршрута, из них будет собран URL в соответствии с типом и определением маршрута.

  • setGotoUrl() может использоваться для установки URL, используемого по умолчанию (когда методу gotoUrl() не был передан URL). Принимает только одну строку URL.

  • setPrependBase() может использоваться для добавления базового URL объекта запроса в начало URL, заданного через методы setGotoUrl(), gotoUrl(), или gotoUrlAndExit().

  • setUseAbsoluteUri() может использоваться для принуждения Redirector-а использовать абсолютные URI при произведении перенаправления. Когда эта опция установлена, то используются значения $_SERVER['HTTP_HOST'], $_SERVER['SERVER_PORT'] и $_SERVER['HTTPS'] для формирования полного URI к URL, определенному одним из методов перенаправления. Эта опция по умолчанию отключена, но может быть включена по умолчанию в последующих релизах.

Кроме того, в Redirector есть различные методы, выполняющие текущие перенаправления:

  • goto() использует setGoto() (интерфейс, подобный _forward()) для построения URL или произведения перенаправления.

  • gotoRoute() использует setGotoRoute() для построения URL и произведения перенаправления.

  • gotoUrl() использует setGotoUrl() (строка URL) для построения URL и произведения перенаправления.

Наконец, можно в любое время получить текущий URL для перенаправления, используя getRedirectUrl().

Базовые примеры использования

Пример #1 Опции настройки

В этом примере переопределяются несколько опций, включая настройку код HTTP статуса, используемого при перенаправлении ('303'), и определение URL, используемого по умолчанию при перенаправлении.

<?php
class SomeController extends Zend_Controller_Action
{
    /**
     * Редиректор - определен для полноты кода
     *
     * @var Zend_Controller_Action_Helper_Redirector
     */
    protected $_redirector = null;
    
    public function init()
    {
        $this->_redirector = $this->_helper->getHelper('Redirector');
        
        // Установка опций по умолчанию для редиректора
        // Поскольку объект зарегистрирован в брокере помощников, то эти опции
        // будут действительными для всех последующих действий
        $this->_redirector->setCode('303')
                          ->setExit(false)
                          ->setGoto("this-action", "some-controller");
    }
    
    public function myAction()
    {
        /* делаем что-то */

        // Перенаправление на ранее зарегистрированный URL и
        // завершение выполнения:
        $this->_redirector->redirectAndExit();
        return; // никогда не будет достигнуто
    }
}
}
            

Пример #2 Использование по умолчанию

Этот пример предполагает, что используются значения по умолчанию, это означает, что после любых перенаправлений будет производиться выход exit().

<?php
// АЛЬТЕРНАТИВНЫЙ ПРИМЕР
class AlternativeController extends Zend_Controller_Action
{
    /**
     * Редиректор - определен для полноты кода
     *
     * @var Zend_Controller_Action_Helper_Redirector
     */
    protected $_redirector = null;
    
    public function init()
    {
        $this->_redirector = $this->_helper->getHelper('Redirector');
    }
    
    public function myAction()
    {
        /* делаем что-то */

        $this->_redirector->gotoUrl('/my-controller/my-action/param1/test/param2/test2');
        // это место никогда не будет достигнуто,
        // т.к. по умолчанию производится переход и завершение выполнения
        return; 
    }
}
            

Пример #3 Использование интерфейса _forward() для goto()

Метод goto() копирует интерфейс метода Zend_Controller_Action::_forward(). Основное отличие состоит в том, что он строит URL из переданных параметров и использует формат :module/:controller/:action/* маршрутизатора по умолчанию. Затем он производит перенаправление вместо добавления действия в цепочку.

<?php
class ForwardController extends Zend_Controller_Action
{
    /**
     * Редиректор - определен для полноты кода
     *
     * @var Zend_Controller_Action_Helper_Redirector
     */
    protected $_redirector = null;
    
    public function init()
    {
        $this->_redirector = $this->_helper->getHelper('Redirector');
    }
    
    public function myAction()
    {
        /* Делаем что-то */

        // Перенаправление на действие 'my-action' контроллера 'my-controller'
        // в текущем модуле с использованием параметров param1 => test и
        // param2 => test2
        $this->_redirector->goto('my-action', 'my-controller', null, array('param1' => 'test', 'param2' => 'test2'));
    }
}
            

Пример #4 Использование маршрута с gotoRoute()

Следующий пример использует метод assemble() маршрута для создания URL, основанного на переданном ассоциативном массиве параметров. Этот пример предполагает, что были зарегистрирован следующий маршрут:

<?php
$route = new Zend_Controller_Router_Route(
    'blog/:year/:month/:day/:id',
    array('controller' => 'archive', 'module' => 'blog', 'action' => 'view')
);
$router->addRoute('blogArchive', $route);
            

При заданном массиве, в котором year (год), month (месяц), и day (день) установлены в 2006, 4 и 24 соответственно, будет построен URL /blog/2006/4/24/42.

<?php
class BlogAdminController extends Zend_Controller_Action
{
    /**
     * Редиректор - определен для полноты кода
     *
     * @var Zend_Controller_Action_Helper_Redirector
     */
    protected $_redirector = null;
    
    public function init()
    {
        $this->_redirector = $this->_helper->getHelper('Redirector');
    }
    
    public function returnAction()
    {
        /* делаем что-то */

        // Перенаправление в архив блога. Строит URL
        // /blog/2006/4/24/42
        
        $this->_redirector->gotoRoute(
            array('year' => 2006, 'month' => 4, 'day' => 24, 'id' => 42),
            'blogArchive'
        );
    }
}
            

ViewRenderer

Введение

Помощник ViewRenderer предназначен для решения следующих задач:

  • Устранение необходимости инстанцирования объектов вида внутри контроллеров; объекты вида будут автоматически регистрироваться вместе с контроллером.

  • Автоматическая установка путей ко скриптам вида, помощникам и фильтрам, определяемая текущим модулем, и автоматическое присоединение имени текущего модуля в качестве префикса имен классов помощников и фильтров.

  • Создание глобально доступного объекта вида для всех запускаемых контроллеров и действий.

  • Возможность для разработчиков устанавливать используемые по умолчанию опции рендеринга вида для всех контроллеров.

  • Добавление возможности автоматического рендеринга скрипта вида, не требующего от разработчика каких-либо действий.

  • Возможность для разработчиков создавать собственные спецификации базового пути вида и путей ко скриптам видов.

Замечание: Если вы вручную производите _forward(), перенаправление или render, то авторендеринг не будет произведен, поскольку выполнение любых этих операций говорит помощнику ViewRenderer, что вы определили свой собственный вывод.

Замечание: ViewRenderer включен по умолчанию. Вы можете отключить его через параметр фронт-контроллера noViewRenderer ($front->setParam('noViewRenderer', true)) или посредством удаления помощника из стека брокера помощников (Zend_Controller_Action_HelperBroker::removeHelper('viewRenderer')).
Если вы хотите изменить настройки ViewRenderer до начала диспетчеризации, то можете сделать это двумя способами:

  • Инстанцировать, зарегистрировать свой объект ViewRenderer, и затем передать его брокеру помощников:

    <?php
    $viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer();
    $viewRenderer->setView($view)
                 ->setViewSuffix('php');
    Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);
                        
  • Инициализировать и/или извлечь по запросу объект ViewRenderer через брокер помощников:

    <?php
    $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
    $viewRenderer->setView($view)
                 ->setViewSuffix('php');
                        

API

В самом базовом его использовании вы просто инстанцируете ViewRenderer и передаете его брокеру помощников. Наиболее легким способом его инстанцирования и регистрации является использование метода getStaticHelper() брокера помощников:

<?php
Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
        

Во время инстанцирования контроллера действий производится вызов ViewRenderer для инстанцирования объекта вида. Каждый раз, когда инстанцируется контроллер, вызывается метод init() помощника ViewRenderer, что приводит к установке свойства $view данного контроллера действий и вызову метода addScriptPath() с путем относительно текущего модуля; он будет вызван с префиксом класса, соответствующим имени текущего модуля, что эффективно разделяет пространства имен всех классов помощников и фильтров, которые вы определили для этого модуля.

Каждый раз, когда вызывается postDispatch(), он будет вызывать render() для текущего действия.

В качестве примера рассмотрим следующий класс:

<?php
// Класс контроллера, модуль foo:
class Foo_BarController extends Zend_Controller_Action
{
    // Рендеринг bar/index.phtml по умолчанию;
    // не требуется производить какие-либо операции
    public function indexAction()
    {
    }

    // Рендеринг bar/populate.phtml с переменной 'foo', установленной в 'bar'.
    // Поскольку объект вида определен в preDispatch(), то он всегда доступен.
    public function populateAction()
    {
        $this->view->foo = 'bar';
    }
}

...

// в одном из ваших скриптов вида:
<?php $this->foo(); // call Foo_View_Helper_Foo::foo()
        

ViewRenderer также определяет несколько аксессоров для того, чтобы можно было устанавливать и получать опции видов:

  • setView($view) позволяет установить объект вида для ViewRenderer. Объект сохраняется в открытом свойстве $view класса.

  • setNeverRender($flag = true) может использоваться для отключения или включения авторендеринга глобально, т.е. для всех контроллеров. Если установлен в true, то postDispatch() не будет автоматически вызывать render() в текущем контроллере. getNeverRender() возвращает текущее значение.

  • setNoRender($flag = true) может использоваться для отключения или включения авторендеринга. Если установлен в true, то postDispatch() не будет автоматически вызывать render() в текущем контроллере. Эта установка сбрасывается каждый раз во время вызова preDispatch() (т.е. нужно устанавливать этот флаг для каждого контроллера, для которого вы не хотите производить авторендеринг). getNoRender() возвращает текущее значение.

  • setNoController($flag = true) может использоваться для того, чтобы указать render(), чтобы он не искал скрипт вида в поддиректории с именем контроллера (что является поведением по умолчанию). getNoController() возвращает текущее значение.

  • setNeverController($flag = true) является аналогом setNoController(), но работает на глобальном уровне - т.е. он не будет сбрасываться с каждым обработанным действием. getNeverController() возвращает текущее значение.

  • setScriptAction($name) может использоваться для того, чтобы указать скрипт действия для рендеринга. $name должен быть именем скрипта без суффикса (и без поддиректории контроллера, за исключением того случая, когда включен noController). Если не задан, то ищется скрипт вида с именем, аналогичным имени действия в объекте запроса. getScriptAction() возвращает текущее значение.

  • setResponseSegment($name) может использоваться для указания того, в какой именованный сегмент объекта ответа следует сохранить результат рендеринга. Если не указан, то выходные данные сохраняются в сегменте, используемом по умолчанию. getResponseSegment() возвращает текущее значение.

  • initView($path, $prefix, $options может вызываться для указания базового пути вида, префикса классов помощников и фильтров, опций помощника ViewRenderer. Вы можете передавать любые из следующих флагов: neverRender, noRender, noController, scriptAction и responseSegment.

  • setRender($action = null, $name = null, $noController = false) позволяет установить scriptAction, responseSegment, или noController за один проход. direct() является псевдонимом для этого метода, что дает возможность легко вызывать этот метод из вашего контроллера.

    // Рендеринг 'foo' вместо текущего скрипта вида
    $this->_helper->viewRenderer('foo');
    
    // Рендеринг form.phtml в сегмент ответа 'html' в обход
    // поддиректории:
    $this->_helper->viewRenderer('form', 'html', true);
    
                    

    Замечание: setRender() и direct() в действительности не производят рендеринг скрипта вида, а устанавливают закрытые свойства помощника, которые postDispatch() и render() будут использовать при рендеринге скрипта вида.

Конструктор позволяет опционально передать объект вида и опции ViewRenderer. Он принимает те же флаги, что и initView():

$view    = new Zend_View(array('encoding' => 'UTF-8'));
$options = array('noController' => true, 'neverRender' => true);
$viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer($view, $options);

        

ViewRenderer имеет несколько дополнительных методов для создания пользовательских спецификаций пути, используемых для определения базового пути вида, добавляемого в объект вида, и пути к определенному скрипту вида, используемого при автоматическом определении скрипта вида для рендеринга. Все эти методы принимают одну или более метку заполнения:

  • :moduleDir ссылается на текущую базовую директорию модуля (по соглашению это директория, родительская по отношению к директории контроллеров модуля).

  • :module ссылается на имя текущего модуля.

  • :controller ссылается на имя текущего контроллера.

  • :action ссылается на имя текущего действия.

  • :suffix ссылается на суффикс скрипта вида (который может быть установлен через setViewSuffix()).

Методы для управления спецификациями пути:

  • setViewBasePathSpec($spec) позволяет изменить спецификацию пути, используемую для определения базового пути, добавляемого в объект вида. По умолчанию используется спецификация :moduleDir/views. Вы можете в любое время получить текущую спецификацицию, используя метод getViewBasePathSpec().

  • setViewScriptPathSpec($spec) позволяет изменить спецификацию пути, используемую для определения пути к отдельному скрипту вида (без базового пути скрипта вида). По умолчанию используется спецификация :controller/:action.:suffix. Вы можете в любое время получить текущую спецификацию, используя метод getViewScriptPathSpec().

  • setViewScriptPathNoControllerSpec($spec) позволяет изменить спецификацию пути, используемую для определения пути к отдельному скрипту вида, когда действует noController (без базового пути скрипта вида). По умолчанию используется спецификация :action.:suffix. Вы можете в любое время получить текущую спецификацию, используя метод getViewScriptPathNoControllerSpec().

Последними элементами в API ViewRenderer-а являются методы для собственно определения путей ко скриптам вида и рендеринга видов. Эти методы включают в себя:

  • renderScript($script, $name) позволяет производить рендеринг скрипта по указанному пути, опционально в заданный именованный сегмент. Если используется этот метод, то ViewRenderer не производит автоматическое определение имени скрипта, вместо этого он напрямую передает аргумент $script методу render() объекта вида.

    Замечание: После того, как был произведен рендеринг вида в объект ответа, устанавливается noRender для предотвращения случайного повторного рендеринга того же скрипта вида.

    Замечание: По умолчанию Zend_Controller_Action::renderScript() вызывает метод renderScript() помощника ViewRenderer.

  • getViewScript($action, $vars) создает путь ко скрипту вида, основываясь на переданном действии $action и/или переменных, переданных в $vars. Этот массив может включать в себя ключи спецификаций пути ('moduleDir', 'module', 'controller', 'action' и 'suffix'). Если переменная была передана, то она будет использована, иначе будут использоваться значения из текущего запроса.

    getViewScript() будет использовать viewScriptPathSpec, либо viewScriptPathNoControllerSpec, в зависимости от установки флага noController.

    Разделители слов в именах модуля, контроллера или действия будут заменены на тире ('-'). Таким образом, если вы имеете контроллер с именем 'foo.bar' и действие 'baz:bat', то при использовании спецификации пути по умолчанию результатом будет путь 'foo-bar/baz-bat.phtml' ко скрипту вида.

    Замечание: По умолчанию Zend_Controller_Action::getViewScript() вызывает метод getViewScript() помощника ViewRenderer.

  • render($action, $name, $noController) сначала проверяет, были ли переданы параметры $name или $noController, и если были переданы, то устанавливает соответствующие флаги (responseSegment и noController соответственно) в ViewRenderer. Затем он передает параметр $action (если есть) методу getViewScript(). Наконец, он передает полученный путь ко скрипту вида методу renderScript().

    Замечание: Следует помнить о побочных эффектах использования render(): значения, передаваемые для имени сегмента ответа и флага noController, сохраняются в объекте. Кроме этого, по окончании рендеринга будет установлен noRender.

    Замечание: По умолчанию Zend_Controller_Action::render() вызывает метод render() помощника ViewRenderer.

  • renderBySpec($action, $vars, $name) позволяет передавать переменные спецификации пути для определения создаваемого пути ко скрипту вида. Он передает $action и $vars методу getScriptPath(), затем передает полученный путь и $name методу renderScript().

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

Пример #5 Базовое использование

В самом базовом использовании вы просто инициализируете и регистрируете помощник ViewRenderer через брокер помощников в своем файле загрузки и затем устанавливаете переменные в своих методах действий.

<?php
// В вашем файле загрузки:
Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');

...

<?php
// Модуль 'foo', контроллер 'bar':
class Foo_BarController extends Zend_Controller_Action
{
    // По умолчанию производится рендеринг bar/index.phtml;
    // дополнительные действия не требуются
    public function indexAction()
    {
    }

    // Рендеринг bar/populate.phtml с переменной 'foo', установленной в 'bar'.
    // Поскольку объект вида был определен в preDispatch(), то он уже
    // доступен для использования.
    public function populateAction()
    {
        $this->view->foo = 'bar';
    }

    // Ничего не рендерится, т.к. производится переход на другое действие;
    // это другое действие может производить рендеринг
    public function bazAction()
    {
        $this->_forward('index');
    }

    // Ничего не рендерится, т.к. производится перенаправление по другому адресу
    public function batAction()
    {
        $this->_redirect('/index');
    }
}
            

Замечание: Соглашения по именованию: Разделители слов в именах контроллера и действия
Если имена вашего контроллера и действия состоят из нескольких слов, то диспетчер требует, чтобы в URL они были разделены определенными символами-разделителями слов и путей. ViewRenderer при создании путей заменяет все найденные в имени контроллера разделители путей действующим разделителем путей ('/') и все разделители слов - чертой ('-'). Таким образом, вызов действия /foo.bar/baz.bat должен быть преобразован в вызов метода FooBarController::bazBatAction() в FooBarController.php, который в свою очередь произведет рендеринг скрипта вида foo-bar/baz-bat.phtml. Вызов действия /bar_baz/baz-bat должен быть преобразован в вызов Bar_BazController::bazBatAction() в Bar/BazController.php (обратите внимание на разделение путей), при этом производится рендеринг bar/baz/baz-bat.phtml.
Во втором примере обратите внимание на то, что по-прежнему используется модуль по умолчанию, но из-за наличия разделителя путей получается имя контроллера Bar_BazController в файле Bar/BazController.php. ViewRenderer имитирует иерархию директорий контроллеров.

Пример #6 Отключение авторендеринга

Может потребоваться отключить авторендеринг для некоторых действий или контроллеров - например, если вы хотите производить вывод разного типа (XML, JSON и т.д.), или просто не хотите ничего выводить. У вас есть два варианта - вы можете полностью отключить авторендеринг (setNeverRender()), либо отключить его для текущего действия (setNoRender()).

<?php
// Класс контроллера baz, модуль bar:
class Bar_BazController extends Zend_Controller_Action
{
    public function fooAction()
    {
        // Не производить авторендеринг в этом действии
        $this->_helper->viewRenderer->setNoRender();
    }
}

// Класс контроллера bat, модуль bar:
class Bar_BatController extends Zend_Controller_Action
{
    public function preDispatch()
    {
        // Не производить авторендеринг во всех действиях этого контроллера
        $this->_helper->viewRenderer->setNoRender();
    }
}
            

Замечание: В большинстве случаев не имеет смысла глобально отключать авторендеринг (через setNeverRender()), поскольку единственная выгода, которую вы получаете в этом случае от использования ViewRenderer - автоматическая установка объекта вида.

Пример #7 Выбор другого скрипта вида

Некоторые ситуации требуют, чтобы производился рендеринг скрипта с именем, отличным от имени действия. Например, если у вас есть контроллер, который имеет методы действий для добавления и редактирования, они оба могут отображать один и тот же вид 'форма', хоть и с разным набором значений. Вы легко можете изменить имя скрипта, используя методы setScriptAction() и setRender(), или вызывая помощника как метод - он произведет вызов метода setRender().

<?php
// Класс контроллера bar, модуль foo:
class Foo_BarController extends Zend_Controller_Action
{
    public function addAction()
    {
        // Рендерить 'bar/form.phtml' вместо 'bar/add.phtml'
        $this->_helper->viewRenderer('form');
    }

    public function editAction()
    {
        // Рендерить 'bar/form.phtml' вместо 'bar/edit.phtml'
        $this->_helper->viewRenderer->setScriptAction('form');
    }

    public function processAction()
    {
        // произведение валидации...
        if (!$valid) {
            // Рендерить 'bar/form.phtml' вместо 'bar/process.phtml'
            $this->_helper->viewRenderer->setRender('form');
            return;
        }

        // иначе продолжение обработки...
    }

}
            

Пример #8 Модификация зарегистрированного объекта вида

А что, если вам нужно модифицировать объект вида - например, изменить пути к помощникам или кодировку? Вы можете делать это как через модификацию объекта вида, установленного в вашем контроллере, так и через извлечение объекта вида из ViewRenderer, оба они являются ссылками на один и тот же объект.

<?php
// Класс контроллера bar, модуль foo:
class Foo_BarController extends Zend_Controller_Action
{
    public function preDispatch()
    {
        // Изменение кодировки вида
        $this->view->setEncoding('UTF-8');
    }

    public function bazAction()
    {
        // Получение объекта вида и указание 'htmlspecialchars'
        // в качестве функции для экранирования
        $view = $this->_helper->viewRenderer->view;
        $view->setEscape('htmlspecialchars');
    }
}
            

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

Пример #9 Изменение спецификаций пути

В некоторых случаях вы можете решить, что спецификации пути, используемые по умолчанию, не соответствуют требованиям вашего сайта. Например, вы можете захотеть иметь одно дерево шаблонов, к которому можно давать доступ дизайнерам (что довольно типично, когда, например, используется » Smarty). В таком случае вы можете захотеть задать жесткую спецификацию базового пути вида и создать альтернативную спецификацию для собственно путей ко скриптам вида.

В рамках данного примера предположим, что базовый путь ко скриптам вида - '/opt/vendor/templates', и вы хотите, чтобы обращение ко скриптам вида производилось по схеме ':moduleDir/:controller/:action.:suffix'. Также предположим, что если флаг noController установлен, то нужно, чтобы использовался верхний уровень вместо поддиректории (':action.:suffix'). И наконец, вы хотите использовать 'tpl' в качестве суффикса имени скрипта вида.

<?php
/**
 * В вашем файле загрузки:
 */

// Другая реализация вида
$view = new ZF_Smarty();

$viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer($view);
$viewRenderer->setViewBasePathSpec('/opt/vendor/templates')
             ->setViewScriptPathSpec(':module/:controller/:action.:suffix')
             ->setViewScriptPathNoControllerSpec(':action.:suffix')
             ->setViewSuffix('tpl');
Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);
            

Пример #10 Рендеринг нескольких скриптов вида из одного действия

Иногда бывает нужно произвести рендеринг нескольких скриптов вида из одного действия. Решение очевидное - просто сделайте несколько вызовов метода render():

<?php
class SearchController extends Zend_Controller_Action
{
    public function resultsAction()
    {
        // Предполагается, что $this->model - текущая модель
        $this->view->results = $this->model->find($this->_getParam('query', '');

        // render() по умолчанию использует ViewRenderer
        // Рендеринг формы поиска и затем результатов поиска
        $this->render('form');
        $this->render('results');
    }

    public function formAction()
    {
        // Ничего не делается. ViewRenderer автоматически производит
        // рендеринг скрипта вида
    }
}
            

Написание собственных помощников

Помощники действий расширяют Zend_Controller_Action_Helper_Abstract, абстрактный класс, который дает базовый интерфейс и функционал, требуемый брокером помощников. Он включает в себя следующие методы:

  • setActionController() используется для установки текущего контроллера действий.

  • init(), запускаемый брокером при инстанцировании, может использоваться для запуска инициализации в помощнике. Это может быть полезным для переустановки состояния, когда несколько контроллеров используют один и тот же помощник в цепочке действий.

  • preDispatch() запускается до запуска действия.

  • postDispatch() запускается тогда, когда запущенное действие завершило свое выполнение - даже если плагин preDispatch() пропустил это действие. Полезно в основном для очистки.

  • getRequest() возвращает текущий объект запроса.

  • getResponse() возвращает текущий объект ответа.

  • getName() возвращает имя помощника. Он извлекает ту часть имени класса, которая следует после последнего символа подчеркивания, иначе возвращается полное имя класса. Например, если класс называется Zend_Controller_Action_Helper_Redirector, то он вернет Zend_Controller_Action_Helper_Redirector, Redirector, а если класс называется FooMessage то он просто вернет свое полное имя.

Вы можете опционально добавить метод direct() в свой класс помощника. Если он определен, то это позволит вам обращаться к помощнику как к методу брокера помощников, этим обеспечивается легкое, единоразовое использование помощника. Например, redirector определяет direct() как псевдоним метода goto(), что позволяет использовать помощника следующим образом:

<?php
// Перенаправление на /blog/view/item/id/42
$this->_helper->redirector('item', 'view', 'blog', array('id' => 42));
        

Метод брокера помощников __call() ищет помощника с именем redirector, затем смотрит, имеет ли помощник определенный метод direct, и, если есть, вызывает его с переданными аргументами.

Создав собственный класс помощника, вы можете предоставить доступ к нему, как описано в разделах выше.


Контроллеры действийAction Controllers
blog comments powered by Disqus

Select a Version

Languages Available

Components

Search the Manual