<sect1 id="zend.controller.actionhelpers" xmlns:xi="http://www.w3.org/2001/XInclude">
    <title>Помощники действий</title>

    <sect2 id="zend.controller.actionhelper.introduction">
        <title>Введение</title>
        <para>
            Помощники действий (action helpers) дают разработчикам возможность
            добавлять функционал во время выполнения или по требованию в любые
            контроллеры действий, которые наследуют от
            <code>Zend_Controller_Action</code>.
            Помощники действий помогают снизить необходимость в наследовании от
            абстрактного контроллера действий при добавлении общего
            функционала в контроллер действий.
        </para>

        <para>
            Есть несколько вариантов использования помощников действий.
            Помощники действий используют брокерскую систему (brokerage system),
            подобную той, которая используется в
            <link linkend="zend.view.helpers">Zend_View_Helper</link> и
            <link linkend="zend.controller.plugins">Zend_Controller_Plugin</link>.
            Помощники действий (как и <code>Zend_View_Helper</code>) могут быть
            загружены и вызваны по требованию, либо инстанцироваться во время
            запроса (начальной загрузки) или создания контроллера действий
            (init()). Для того, чтобы лучше разобраться с этим, см. ниже раздел
            по использованию.
        </para>
    </sect2>

    <sect2 id="zend.controller.actionhelper.initialization">
        <title>Инициализация помощника</title>

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

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

        <itemizedlist>
            <listitem>
                <para>
                    Явное использование метода <code>getHelper()</code>. Просто
                    передайте ему имя, и будет возвращен объект помощника:
                </para>

                <programlisting role="php"><![CDATA[
$flashMessenger = $this->_helper->getHelper('FlashMessenger');
$flashMessenger->addMessage('We did something in the last request');
]]>
                </programlisting>
            </listitem>

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

                <programlisting role="php"><![CDATA[
$flashMessenger = $this->_helper->FlashMessenger;
$flashMessenger->addMessage('We did something in the last request');
]]>
                </programlisting>
            </listitem>

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

                <programlisting role="php"><![CDATA[
$this->_helper->FlashMessenger('We did something in the last request');
]]>
                </programlisting>
            </listitem>
        </itemizedlist>

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

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

    <sect2 id="zend.controller.actionhelper.broker">
        <title>Брокер помощников</title>

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

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

        <programlisting role="php"><![CDATA[
Zend_Controller_Action_HelperBroker::addHelper($helper);
]]>
        </programlisting>

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

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

                <programlisting role="php"><![CDATA[
// Добавление помощников, начинающихся
// с My_Action_Helpers в My/Action/Helpers/
Zend_Controller_Action_HelperBroker::addPrefix('My_Action_Helpers');
]]>
                </programlisting>
            </listitem>

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

                <programlisting role="php"><![CDATA[
// Добавление помощников, начинающихся с Helper в Plugins/Helpers/
Zend_Controller_Action_HelperBroker::addPath('./Plugins/Helpers',
                                             'Helper');
]]>
                </programlisting>
            </listitem>
        </itemizedlist>

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

        <para>
            Внутри себя брокер помощников использует <link
                linkend="zend.loader.pluginloader">экземпляр PluginLoader</link>
            для поддержки путей. Вы можете извлечь PluginLoader, используя
            статический метод <code>getPluginLoader()</code>, или
            добавить свой экземпляр PluginLoader, используя
            <code>setPluginLoader()</code>.
        </para>

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

        <programlisting role="php"><![CDATA[
// Проверка, зарегистрирован ли помощник 'redirector' в брокере:
if (Zend_Controller_Action_HelperBroker::hasHelper('redirector')) {
    echo 'Redirector helper registered';
}
]]>
        </programlisting>

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

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

        <programlisting role="php"><![CDATA[
// Проверка, зарегистрирован ли помощник 'redirector' в брокере,
// и его извлечение:
if (Zend_Controller_Action_HelperBroker::hasHelper('redirector')) {
    $redirector =
        Zend_Controller_Action_HelperBroker::getExistingHelper('redirector');
}

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

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

        <programlisting role="php"><![CDATA[
// Удаление помощника 'redirector' из брокера, помещенное
// в условную конструкцию
if (Zend_Controller_Action_HelperBroker::hasHelper('redirector')) {
    Zend_Controller_Action_HelperBroker::removeHelper('redirector')
}
]]>
        </programlisting>
    </sect2>

    <sect2 id="zend.controller.actionhelper.stockhelpers">
        <title>Встроенные помощники действий</title>

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

        <xi:include href="Zend_Controller-ActionHelpers-ActionStack.xml">
            <xi:fallback><xi:include href="../../en/module_specs/Zend_Controller-ActionHelpers-ActionStack.xml" /></xi:fallback>
        </xi:include>
        <xi:include href="Zend_Controller-ActionHelpers-AutoComplete.xml">
            <xi:fallback><xi:include href="../../en/module_specs/Zend_Controller-ActionHelpers-AutoComplete.xml" /></xi:fallback>
        </xi:include>
        <xi:include href="Zend_Controller-ActionHelpers-ContextSwitch.xml">
            <xi:fallback><xi:include href="../../en/module_specs/Zend_Controller-ActionHelpers-ContextSwitch.xml" /></xi:fallback>
        </xi:include>
        <xi:include href="Zend_Controller-ActionHelpers-FlashMessenger.xml">
            <xi:fallback><xi:include href="../../en/module_specs/Zend_Controller-ActionHelpers-FlashMessenger.xml" /></xi:fallback>
        </xi:include>
        <xi:include href="Zend_Controller-ActionHelpers-Json.xml">
            <xi:fallback><xi:include href="../../en/module_specs/Zend_Controller-ActionHelpers-Json.xml" /></xi:fallback>
        </xi:include>
        <xi:include href="Zend_Controller-ActionHelpers-Redirector.xml">
            <xi:fallback><xi:include href="../../en/module_specs/Zend_Controller-ActionHelpers-Redirector.xml" /></xi:fallback>
        </xi:include>
        <xi:include href="Zend_Controller-ActionHelpers-ViewRenderer.xml">
            <xi:fallback><xi:include href="../../en/module_specs/Zend_Controller-ActionHelpers-ViewRenderer.xml" /></xi:fallback>
        </xi:include>
    </sect2>

    <sect2 id="zend.controller.actionhelper.writingyourown">
        <title>Написание собственных помощников</title>

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

        <itemizedlist>
            <listitem>
                <para>
                    <code>setActionController()</code> используется для
                    установки текущего контроллера действий.
                </para>
            </listitem>

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

            <listitem>
                <para>
                    <code>preDispatch()</code> запускается до того, как будет
                    запущено действие.
                </para>
            </listitem>

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

            <listitem>
                <para>
                    <code>getRequest()</code> возвращает текущий объект запроса.
                </para>
            </listitem>

            <listitem>
                <para>
                    <code>getResponse()</code> возвращает текущий объект ответа.
                </para>
            </listitem>

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

        <para>
            Вы можете опционально добавить метод <code>direct()</code> в свой
            класс помощника. Если он определен, то это позволит вам обращаться к
            помощнику как к методу брокера помощников, этим обеспечивается
            легкое единовременное использование помощника. Например,
            <link linkend="zend.controller.actionhelpers.redirector">redirector</link>
            определяет <code>direct()</code> как псевдоним метода
            <code>goto()</code>, что позволяет использовать помощника следующим
            образом:
        </para>

        <programlisting role="php"><![CDATA[
// Перенаправление на /blog/view/item/id/42
$this->_helper->redirector('item', 'view', 'blog', array('id' => 42));
]]>
        </programlisting>

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

        <para>
            Создав собственный класс помощника, вы можете предоставить доступ к
            нему, как описано в разделах выше.
        </para>
    </sect2>
</sect1>
<!--
vim:se ts=4 sw=4 et:
-->