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

## Введение

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

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

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

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

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

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

      $flashMessenger = $this->_helper->getHelper('FlashMessenger');
      $flashMessenger->addMessage('We did something in the last request');

- Используйте функционал "волшебного" метода `__get()` брокера помощников - извлекайте помощника так же, как если бы он был свойством этого брокера:

      $flashMessenger = $this->_helper->FlashMessenger;
      $flashMessenger->addMessage('We did something in the last request');

- И наконец, большинство помощников действий реализует метод `direct()`, который будет вызывать особый, используемый по умолчанию метод в помощнике. Например, в случае `FlashMessenger` будет вызван метод `addMessage()`:

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

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

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

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

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

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

    Zend_Controller_Action_HelperBroker::addHelper($helper);

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

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

      // Добавление помощников, начинающихся
      // с My_Action_Helpers в My/Action/Helpers/
      Zend_Controller_Action_HelperBroker::addPrefix('My_Action_Helpers');

- `addPath()` принимает директорию в качестве первого аргумента и префикс класса в качестве второго (по умолчанию это 'Zend_Controller_Action_Helper'). Это позволяет поставить в соответствие определенным директориям собственные префиксы классов.

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

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

Внутри себя брокер помощников использует экземпляр PluginLoader для поддержки путей. Вы можете извлечь PluginLoader, используя статический метод `getPluginLoader()`, или добавить свой экземпляр PluginLoader, используя `setPluginLoader()`.

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

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

Есть также два статических метода для извлечения помощников из брокера помощников: `getExistingHelper()` и `getStaticHelper()`. `getExistingHelper()` будет извлекать помощника только если он был ранее вызван или явно зарегистрирован через брокер помощников, иначе бросается исключение. `getStaticHelper()` делает то же самое, что и `getExistingHelper()`, за тем исключением, что будет пытаться инстанцировать помощника, если он еще не был зарегистрирован в стеке помощников. `getStaticHelper()` является хорошим выбором, если нужно извлечь помощника для конфигурирования.

Оба метода принимают единственный аргумент, `$name`, который является коротким именем помощника (без префикса).

    // Проверка, зарегистрирован ли помощник 'redirector' в брокере,
    // и его извлечение:
    if (Zend_Controller_Action_HelperBroker::hasHelper('redirector')) {
        $redirector =
            Zend_Controller_Action_HelperBroker::getExistingHelper('redirector');
    }

    // Или просто извлеките его, не заботясь о том,
    // был ли он ранее зарегистрирован:
    $redirector =
        Zend_Controller_Action_HelperBroker::getStaticHelper('redirector');
    }

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

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

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

Zend Framework уже содержит в себе набор помощников действий: `AutoComplete` автоматизирует ответы для автозавершения ввода с использованием AJAX; `ContextSwitch` и `AjaxContext` для обслуживания альтернативных форматов ответов для ваших действий; `FlashMessenger` для управления сессионными сообщениями; `Json` для кодирования и отправки ответов JSON; `Redirector`, предоставляющий различные реализации перенаправления из вашего приложения на внутренние и внешние страницы; и `ViewRenderer`, автоматизирующий процесс настройки объекта вида в контроллерах и рендеринга видов.

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

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

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

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

- `preDispatch()` запускается до того, как будет запущено действие.

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

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

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

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

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

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

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

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