7.7. Контроллеры действий

7.7.1. Введение

Zend_Controller_Action является абстрактным классом, который можно использовать в реализации контроллеров действий для последующего их использования с фронт-контроллером при разработке сайта, основанного на паттерне Model-View-Controller (MVC).

Для того, чтобы использовать Zend_Controller_Action, нужно создать его подкласс в действующей директории контроллеров (или расширить его для создания своего базового класса контроллеров действий). Подкласс может содержать методы действий, которые соответствуют различным действиям, которыми должен управлять контроллер. Маршрутизатор и диспетчер компоненты Zend_Controller будут рассматривать любые методы в классе контроллера с именем, заканчивающимся на 'Action', как возможные действия контроллеров.

Для примера предположим, что ваш класс определен следующим образом:

class FooController extends Zend_Controller_Action
{
    public function barAction()
    {
        // do something
    }

    public function bazAction()
    {
        // do something
    }
}

Приведенный выше класс FooController (контроллер 'foo') определяет два действия - 'bar' и 'baz'.

Класс может быть дополнен инициализирующим методом, методом, используемым по умолчанию (если не был вызван метод, либо вызван несуществующий метод), перехватчиками pre- и post-dispatch и различными вспомогательными методами.

7.7.2. Инициализация объекта

Несмотря на то, что вы всегда можете переопределить конструктор контроллера действий, мы не рекомендуем делать этого. Zend_Controller_Action::__construct() выполняет некоторые важные задачи, такие, как регистрация объектов запроса и ответа, аргументов вызова, переданных из фронт-контроллера. Если необходимо переопределить контроллер, то всегда вызывайте конструктор родительского класса parent::__construct($request, $response, $invokeArgs) в конструкторе подкласса.

Для осуществления своего инстанцирования более подходящим является метод init(), который вызывается в конце __construct(). Например, если вы хотите устанавливать соединение с БД при инстанцировании:

class FooController extends Zend_Controller_Action
{
    public function init()
    {
        $this->db = Zend_Db::factory('Pdo_Mysql', array(
            'host'     => 'myhost',
            'username' => 'user',
            'password' => 'XXXXXXX',
            'dbname'   => 'website'
        ));
    }
}

7.7.3. Перехватчики Pre- и Post-Dispatch

Zend_Controller_Action определяет два метода, которые вызываются до и после требуемого действия, preDispatch() и postDispatch(). Они могут быть полезны во многих случаях: проверка аутентификации и прав пользователя до запуска действия (действие может быть пропущено через вызов _forward() в preDispatch()) или размещение сгенерированного содержимого в боковой части сайта (метод postDispatch()).

7.7.4. Методы доступа

Вместе с объектом регистрируются некоторые объекты и переменные, для них есть свои методы доступа.

  • Объект запроса: getRequest() может использоваться для получения объекта запроса, используемого при вызове действия.

  • Объект ответа: getResponse() может использоваться для получения объекта ответа. Некоторые типичные вызовы могут выглядеть следующим образом:

    $this->getResponse()->setHeader('Content-Type', 'text/xml');
    $this->getResponse()->appendBody($content);
    
  • Аргументы вызова: фронт-контроллер может добавлять параметры в маршрутизатор, диспетчер и контроллер действий. Для их получения используйте getInvokeArg($key), можно также извлечь весь список аргументов, используя метод getInvokeArgs().

  • Параметры запроса: Объект запроса включает в себя параметры запроса, такие, как значения _GET, _POST, или параметры, определенные в пути URL. Для их получения используйте _getParam($key) или _getAllParams(). Вы можете также установить параметры запроса, используя метод _setParam(), это полезно при перенаправлении на другие действия через метод _forward().

    Для определения того, существует ли параметр или нет (полезно для логического ветвления), используйте _hasParam($key).

7.7.5. Вспомогательные методы

Кроме методов доступа, Zend_Controller_Action имеет несколько вспомогательных методов для выполнения некотрорых общих задач в методах действий (или в pre-/post-dispatch).

  • _forward($action, $controller = null, $module = null, array $params = null): выполняет другое действие. Если этоот метод вызывается в preDispatch(), то текущее действие будет пропущено, вместо этого начинает выполняться другое действие. В остальных случаях выполнение этого действия начинается только после выполнения текущего действия.

  • _redirect($url, array $options = array()): перенаправляет по другому URL. Этот метод принимает URL и необязательный набор опций. По умолчанию он выполняет перенаправление HTTP 302.

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

    • exit: whether or not to exit immediately. If requested, it will cleanly close any open sessions and perform the redirect.

      You may set this option globally within the controller using the setRedirectExit() accessor.

    • prependBase: whether or not to prepend the base URL registered with the request object to the URL provided.

      You may set this option globally within the controller using the setRedirectPrependBase() accessor.

    • code: what HTTP code to utilize in the redirect. By default, an HTTP 302 is utilized; any code between 301 and 306 may be used.

      You may set this option globally within the controller using the setRedirectCode() accessor.

  • render($action = null, $name = null, $noController = false): render a view script. If no arguments are passed, it assumes that the script requested is [controller]/[action].phtml (where .phtml is the value of the $viewSuffix property). Passing a value for $action will render that template in the [controller] subdirectory. To override using the [controller] subdirectory, pass a true value for $noController. Finally, templates are rendered into the response object; if you wish to render to a specific named segment in the response object, pass a value to $name.

    Some examples:

    <?php
    class MyController extends Zend_Controller_Action
    {
        public function fooAction()
        {
            // Renders my/foo.phtml
            $this->render();
    
            // Renders my/bar.phtml
            $this->render('bar');
    
            // Renders baz.phtml
            $this->render('baz', null, true);
    
            // Renders foo/login.phtml to the 'form' segment of the response object
            $this->render('login', 'form');
            
            // Renders site.phtml to the 'page' segment of the response object
            $this->render('site', 'page', true);
        }
    }
    
  • initView(): initialize the view object. render() calls initView() in order to retrieve the view object, but it may be initialized at any time; by default it populates the $view property. By default, it uses Zend_View, but any class implementing Zend_View_Interface may be used.

    The default implementation makes the following assumption of the directory structure:

    applicationOrModule/
        controllers/
            IndexController.php
        views/
            scripts/
                index/
                    index.phtml
            helpers/
            filters/
    

    In other words, view scripts are assumed to be in the views/scripts/ subdirectory, and the views subdirectory is assumed to be a sibling of the controllers subdirectory.

    Call initView() in either init() or your action methods if you need to be able to assign variables, register filters, etc. As examples:

    <?php
    class MyController extends Zend_Controller_Action
    {
        public function init()
        {
            // Initialize view object immediately
            $this->initView();
        }
    
        public function fooAction()
        {
            // Initialize some variables
            $this->view->foo = 'bar';
            $this->view->bar = 'baz';
    
            // render the view, with the 'foo' and 'bar' assigned variables
            $this->render();
        }
    }
    
    class FooController extends Zend_Controller_Action
    {
        public function barAction()
        {
            // Initialize view on a per-action basis:
            $view = $this->initView();
    
            // Initialize some variables
            $view->foo = 'bar';
            $view->bar = 'baz';
    
            // render the view, with the 'foo' and 'bar' assigned variables
            $this->render();
        }
    }
    
  • getViewScript($action = null, $noController = false): retrieve a view script path. Primarily used by render(), you can call this at any time to grab a view script path, or override the method to change how your controller determines the path to a view script.

    As detailed under render(), above, the default functionality is to look for a view script named [controller]/[action].phtml. Providing $action will override the filename of the view script, and passing a true value to $noController will override looking in the controller subdirectory. You may also override the $viewSuffix property to change the file extension used (defaults to .phtml).

    Override this method to provide alternate functionality when determining the view script name and path.