| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- Reviewed: no -->
- <sect1 id="zend.controller.front">
- <title>Фронт-контроллер</title>
- <sect2 id="zend.controller.front.overview">
- <title>Обзор</title>
- <para>
- <classname>Zend_Controller_Front</classname> реализует
- <ulink url="http://www.martinfowler.com/eaaCatalog/frontController.html">паттерн
- Front Controller</ulink>, используемый в приложениях <ulink
- url="http://en.wikipedia.org/wiki/Model-view-controller">MVC</ulink>.
- Его назначение состоит в инициализации окружения запроса, проложении
- маршрута приходящего запроса и последующем запуске выявленных
- действий. Он агрегирует все ответы и возвращает их по завершении
- процесса.
- </para>
- <para>
- <classname>Zend_Controller_Front</classname> также реализует
- <ulink url="http://en.wikipedia.org/wiki/Singleton_pattern">паттерн
- Singleton</ulink>, это означает, что в любое время может быть
- доступен только один экземпляр этого класса. Это позволяет ему также
- выступать в качестве реестра, в котором хранятся другие объекты,
- участвующие в процессе диспетчеризации.
- </para>
- <para>
- <classname>Zend_Controller_Front</classname> регистрирует в себе <link
- linkend="zend.controller.plugins">брокер плагинов</link> (plugin
- broker), что позволяет с помощью плагинов отслеживать события,
- инициируемые фронт-контроллером.
- В большинстве случаев это дает возможность подгонять
- процесс диспетчеризации под конкретный сайт без расширения
- фронт-контроллера для добавления функциональности.
- </para>
- <para>
- Фронт-контроллеру для его работы необходим, как минимум,
- один или более путей к директориям, содержащим
- <link linkend="zend.controller.action">контроллеры действий</link>.
- Можно также использовать различные методы для дальнейшей
- настройки конфигураций фронт-контроллера и его помощников.
- </para>
- <note>
- <title>Поведение по умолчанию</title>
- <para>
- По умолчанию фронт-контроллер загружает плагин <link
- linkend="zend.controller.plugins.standard.errorhandler">ErrorHandler</link>
- и помощник действий <link
- linkend="zend.controller.actionhelpers.viewrenderer">ViewRenderer</link>.
- Это сделано для упрощения обработки ошибок и рендеринга видов в
- контроллерах, соответственно.
- </para>
- <para>
- Для того, чтобы отключить <code>ErrorHandler</code>, произведите
- следующее до вызова метода <code>dispatch()</code>:
- </para>
- <programlisting language="php"><![CDATA[
- // Отключение плагина ErrorHandler:
- $front->setParam('noErrorHandler', true);
- ]]></programlisting>
- <para>
- Для того, чтобы отключить <code>ViewRenderer</code>, сделайте
- следующее до вызова метода <code>dispatch()</code>:
- </para>
- <programlisting language="php"><![CDATA[
- // Отключение помощника ViewRenderer:
- $front->setParam('noViewRenderer', true);
- ]]></programlisting>
- </note>
- </sect2>
- <sect2 id="zend.controller.front.methods.primary">
- <title>Ключевые методы</title>
- <para>
- Фронт-контроллер имеет несколько аксессоров для настройки его
- конфигурации. Тем не менее, он имеет несколько ключевых в
- его функционале методов.
- </para>
- <sect3 id="zend.controller.front.methods.primary.getinstance">
- <title>getInstance()</title>
- <para>
- <code>getInstance()</code> используется для получения экземпляра
- фронт-контроллера. Поскольку фронт-контроллер реализует паттерн
- Singleton, то это также единственно доступный способ
- инстанцирования объекта фронт-контроллера.
- </para>
- <programlisting language="php"><![CDATA[
- $front = Zend_Controller_Front::getInstance();
- ]]></programlisting>
- </sect3>
- <sect3 id="zend.controller.front.methods.primary.setcontrollerdirectory">
- <title>setControllerDirectory() и addControllerDirectory()</title>
- <para>
- <code>setControllerDirectory()</code> используется для того,
- чтобы указать <link
- linkend="zend.controller.dispatcher">диспетчеру</link>, где
- искать файлы классов <link
- linkend="zend.controller.action">контроллеров действий</link>.
- Он принимает один путь или ассоциативный массив пар
- модуль => путь в качестве параметра.
- </para>
- <para>
- Примеры:
- </para>
- <programlisting language="php"><![CDATA[
- // Установка директории контроллеров, используемой по умолчанию:
- $front->setControllerDirectory('../application/controllers');
- // Одновременная установка нескольких директорий модулей:
- $front->setControllerDirectory(array(
- 'default' => '../application/controllers',
- 'blog' => '../modules/blog/controllers',
- 'news' => '../modules/news/controllers',
- ));
- // Добавление директории модуля 'foo':
- $front->addControllerDirectory('../modules/foo/controllers', 'foo');
- ]]></programlisting>
- <note>
- <para>
- Если вы используете <code>addControllerDirectory()</code>
- без имени модуля, то он установит директорию для модуля
- <code>default</code>. Если директория уже существует, то она
- будет перезаписана.
- </para>
- </note>
- <para>
- Можно получить текущие установки для директорий
- контроллеров, используя метод
- <code>getControllerDirectory()</code>. Он вернет массив пар
- модуль => директория.
- </para>
- </sect3>
- <sect3 id="zend.controller.front.methods.primary.addmoduledirectory">
- <title>addModuleDirectory() и getModuleDirectory()</title>
- <para>
- Одной из возможностей фронт-контроллера является то, что вы
- можете <link
- linkend="zend.controller.modular">определять модульную
- структуру директорий</link> для создания отдельных компонент,
- которые называются "модулями".
- </para>
- <para>
- Каждый модуль должен находиться в собственной директории и
- отражать структуру директорий используемого по умолчанию
- модуля - т.е., он должен содержать, как минимум, поддиректорию
- "controllers"; с ней, как правило, присутствует поддиректория
- "views" и другие поддиректории приложения.
- </para>
- <para>
- Метод <code>addModuleDirectory()</code> позволяет передавать имя
- директории, содержащей один или более директорий модулей.
- Он их сканирует и добавляет в качестве директорий контроллеров
- во фронт-контроллер.
- </para>
- <para>
- Если вы хотите получить путь к определенному модулю или к
- текущему модулю, то можете использовать метод
- <code>getModuleDirectory()</code>, при передаче имени модуля он
- возвращает путь к нему, иначе возвращается путь к текущему
- модулю.
- </para>
- </sect3>
- <sect3 id="zend.controller.front.methods.primary.dispatch">
- <title>dispatch()</title>
- <para>
- <code>dispatch(Zend_Controller_Request_Abstract $request = null,
- Zend_Controller_Response_Abstract $response = null)</code>
- является "рабочей лошадкой" фронт-контроллера. Он может
- опционально принимать
- <link linkend="zend.controller.request">объект
- запроса</link> и/или
- <link linkend="zend.controller.response">объект
- ответа</link>, что дает разработчикам возможность передавать
- свои объекты.
- </para>
- <para>
- Если методу <code>dispatch()</code> не были переданы объект
- запроса или ответа, то он будет проверять, были ли ранее
- зарегистрированы объекты, и использовать их, либо инстанцировать
- версии по умолчанию (в обоих случаях по умолчанию будут
- использоваться разновидность HTTP).
- </para>
- <para>
- Аналогичным образом <code>dispatch()</code> производит проверку
- на уже зарегистрированные объекты
- <link linkend="zend.controller.router">маршрутизатора</link> и
- <link linkend="zend.controller.dispatcher">диспетчера</link>, и
- если они не найдены, то инстанцирует версии по умолчанию.
- </para>
- <para>
- Процесс диспетчеризации имеет три отдельных события:
- </para>
- <itemizedlist>
- <listitem><para>
- Маршрутизация
- </para></listitem>
- <listitem><para>
- Диспетчеризация
- </para></listitem>
- <listitem><para>
- Ответ
- </para></listitem>
- </itemizedlist>
- <para>
- Маршрутизация производится только один раз, когда вызывается
- <code>dispatch()</code>, при этом используются значения в
- объекте запроса. Диспетчеризация производится циклически. Запрос
- может означать вызов нескольких действий, контроллер или плагин
- могут сбрасывать объект запроса для дополнительного вызова
- других действий. Когда все действия выполнены, фронт-контроллер
- возвращает ответ.
- </para>
- </sect3>
- <sect3 id="zend.controller.front.methods.primary.run">
- <title>run()</title>
- <para>
- <code>Zend_Controller_Front::run($path)</code> - статический
- метод, принимающий только путь к директории контроллеров. Он
- извлекает экземпляр фронт-контроллера через
- <link linkend="zend.controller.front.methods.primary.getinstance">getInstance()</link>),
- регистрирует этот путь через
- <link linkend="zend.controller.front.methods.primary.setcontrollerdirectory">setControllerDirectory()</link>, и в конце вызывает метод <link linkend="zend.controller.front.methods.primary.dispatch">dispatch()</link>.
- </para>
- <para>
- В сущности, <code>run()</code> представляет собой удобный
- метод, который можно использовать при разработке сайта, не
- требующего специальной настройки фронт-контроллера.
- </para>
- <programlisting language="php"><![CDATA[
- // Инстанцирование фронт-контроллера, установка директории контроллера и
- // выполнение диспетчеризации в одном вызове:
- Zend_Controller_Front::run('../application/controllers');
- ]]></programlisting>
- </sect3>
- </sect2>
- <sect2 id="zend.controller.front.methods.environment">
- <title>Методы-аксессоры для конфигурирования</title>
- <para>
- Кроме методов, перечисленных выше, есть методы-аксессоры, которые
- можно использовать для управления конфигурацией фронт-контроллера -
- и одновременно конфигурацией классов, которым фронт-контроллер
- делегирует выполнение.
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <code>resetInstance()</code> может использоваться для сброса
- всех текущих настроек. Он в основном предназначен для
- тестирования, но может также использоваться в тех случаях,
- когда нужно связать между собой несколько
- фронт-контроллеров.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>(set|get)DefaultControllerName()</code> позволяют
- установить другое имя используемого
- по умолчанию контроллера (иначе используется 'index') и
- получить текущее значение. Они служат посредниками к
- <link linkend="zend.controller.dispatcher">диспетчеру</link>.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>(set|get)DefaultAction()</code> позволяют
- установить другое имя используемого по умолчанию действия
- (иначе используется 'index') и получить текущее
- значение. Они служат посредниками к
- <link linkend="zend.controller.dispatcher">диспетчеру</link>.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>(set|get)Request()</code> позволяют установить
- класс <link linkend="zend.controller.request">запроса</link>
- или его объект для использования в процессе диспетчеризации
- и получить текущий объект. При установке объекта
- запроса вы можете передать имя класса запроса, в этом случае
- метод загрузит файл класса и инстанцирует его.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>(set|get)Router()</code> позволяют установить
- класс
- <link linkend="zend.controller.router">маршрутизатора</link>
- или его объект, используемые в течение процесса
- диспетчеризации, и получить текущий объект. Когда
- устанавливается объект маршрутизатора, вы можете передать
- имя класса маршрутизатора, в этом случае метод загрузит файл
- класса и инстанцирует его.
- </para>
- <para>
- При извлечении объекта маршрутизатора сначала производится
- проверка, представлен ли во фронт-контроллере такой объект и
- в случае его отсутствия инстанцирует используемый по
- умолчанию маршрутизатор (Rewrite Router).
- </para>
- </listitem>
- <listitem>
- <para>
- <code>(set|get)BaseUrl()</code> дают возможность установить
- <link linkend="zend.controller.request.http.baseurl">базовый
- URL</link>, который удаляется из начала при
- маршрутизации запросов, и получить его текущее значение.
- Это значение передается объекту запроса непосредственно до
- маршрутизации.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>(set|get)Dispatcher()</code> дают возможность
- установки класса
- <link linkend="zend.controller.dispatcher">диспетчера</link>
- или его объекта для использования в течение диспетчеризации,
- и получения текущего объекта. При установке объекта
- диспетчера можно передать имя класса диспетчера, в этом
- случае метод загрузит файл класса и инстанцирует его.
- </para>
- <para>
- При извлечении объекта диспетчера, метод сначала производит
- проверку того, представлен ли во фронт-контроллере такой
- объект и в случае его отсутствия инстанцирует диспетчер,
- используемый по умолчанию.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>(set|get)Response()</code> дают возможность установить
- класс <link linkend="zend.controller.response">ответа</link>
- или его объект для использования в процессе диспетчеризации,
- и извлечь текущий объект. При установке объекта
- ответа можно передать имя класса ответа, в этом случае метод
- загрузит файл класса и инстанцирует его.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>registerPlugin(Zend_Controller_Plugin_Abstract $plugin, $stackIndex = null)</code>
- позволяет регистрировать <link
- linkend="zend.controller.plugins">объекты плагинов</link>.
- Путем установки опционального параметра
- <varname>$stackIndex</varname>, вы можете
- контролировать порядок, в котором выполняются плагины.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>unregisterPlugin($plugin)</code> позволяет отменять
- регистрацию <link
- linkend="zend.controller.plugins">объектов плагинов</link>.
- <varname>$plugin</varname> может быть как объектом плагина, так и строкой, обозначающей класс плагина, регистрацию которого надо отменить.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>throwExceptions($flag)</code> используется для
- включения/отключения возможности генерации исключений в
- течение процесса диспетчеризации. По умолчанию исключения
- отлавливаются и размещаются в
- <link linkend="zend.controller.response">объекте
- ответа</link>; включение <code>throwExceptions()</code>
- переопределит это поведение
- </para>
- <para>
- Более полробную информацию читайте в <xref linkend="zend.controller.exceptions"/>.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>returnResponse($flag)</code> используется для того,
- чтобы указать фронт-контроллеру - возвращать ли ответ
- из <code>dispatch()</code> (<constant>TRUE</constant>), либо ответ
- должен быть отправлен автоматически (<constant>FALSE</constant>). По
- умолчанию ответ отправляется автоматически
- (через вызов
- <code>Zend_Controller_Response_Abstract::sendResponse()</code>);
- включение <code>returnResponse()</code> переопределит это
- поведение.
- </para>
- <para>
- Ситуации, в которых может потребоваться возврат ответа,
- включают в себя проверку на предмет исключений до отправки
- ответа клиенту, необходимость журналирования различных
- аспектов ответа (таких, как заголовки) и т.д.
- </para>
- </listitem>
- </itemizedlist>
- </sect2>
- <sect2 id="zend.controller.front.methods.params">
- <title>Параметры фронт-контроллера</title>
- <para>
- Во введении мы указали на то, что фронт-контроллер также выступает
- как реестр для различных компонент контроллера. Это реализуется
- через группу методов для параметров. Эти методы позволяют
- регистрировать произвольные данные - объекты и переменные - во
- фронт-контроллере, чтобы их можно было извлечь в любой точке цепочки
- диспетчеризации. Эти значения передаются маршрутизатору, диспетчеру,
- и контроллерам действий. Эти методы включают в себя:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <code>setParam($name, $value)</code> дает возможность
- установить единственный параметр с именем <varname>$name</varname>
- и значением <varname>$value</varname>.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>setParams(array $params)</code> позволяет
- установить несколько параметров одновременно с помощью
- ассоциативного массива.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>getParam($name)</code> дает возможность извлечь один
- параметр за один раз, используя его имя <varname>$name</varname> в
- качестве идентификатора.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>getParams()</code> позволяет извлечь все
- параметры за один раз.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>clearParams()</code> позволяет удалить один параметр
- (путем передачи строкового идентификатора), нескольких
- параметров (путем передачи массива строковых
- идентификаторов) или весь стек параметров (без передачи
- чего-либо).
- </para>
- </listitem>
- </itemizedlist>
- <para>
- Есть несколько предопределенных параметров специально для
- использования в цепочке диспетчеризации:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <code>useDefaultControllerAlways</code> используется для
- указания
- <link linkend="zend.controller.dispatcher">диспетчеру</link>,
- что следует использовать контроллер по умолчанию в модуле
- по умолчанию для любых запросов, диспетчеризация которых
- невозможна (т.е. модуль, контроллер и/или действие не
- существуют). По умолчанию он отключен.
- </para>
- <para>
- См. <xref linkend="zend.controller.exceptions.internal"/> за
- более подробной информацией об использовании этого параметра
- настройки.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>disableOutputBuffering</code> используется для
- указания
- <link linkend="zend.controller.dispatcher">диспетчеру</link>,
- что не следует использовать буферизацию вывода для сбора
- данных на вывод, генерируемых контроллерами действий. По
- умолчанию диспетчер собирает весь вывод и присоединяет его к
- телу содержимого в объекте ответа.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>noViewRenderer</code> используется для отключения
- помощника <link
- linkend="zend.controller.actionhelpers.viewrenderer">ViewRenderer</link>.
- Установите этот параметр в true для его отключения.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>noErrorHandler</code> используется для отключения
- <link
- linkend="zend.controller.plugins.standard.errorhandler">плагина
- Error Handler</link>
- Установите этот параметр в true для его отключения.
- </para>
- </listitem>
- </itemizedlist>
- </sect2>
- <sect2 id="zend.controller.front.subclassing">
- <title>Расширение фронт-контроллера</title>
- <para>
- При наследовании от фронт-контроллера, необходимо, как
- минимум, переопределить метод <code>getInstance()</code>.
- </para>
- <programlisting language="php"><![CDATA[
- class My_Controller_Front extends Zend_Controller_Front
- {
- public static function getInstance()
- {
- if (null === self::$_instance) {
- self::$_instance = new self();
- }
- return self::$_instance;
- }
- }
- ]]></programlisting>
- <para>
- Такое переопределение метода <code>getInstance()</code> гарантирует
- то, что последующий вызов
- <code>Zend_Controller_Front::getInstance()</code> вернет экземпляр
- созданного вами подкласса вместо экземпляра
- <classname>Zend_Controller_Front</classname> - это особенно полезно
- для некоторых альтернативных маршрутизаторов и помощников видов.
- </para>
- <para>
- Как правило, нет необходимости создавать подклассы
- фронт-контроллера, если только не нужно добавить новый
- функционал (например, автозагрузку плагинов или способ
- определения путей к помощникам действий). Целями, для достижения
- которых может потребоваться изменение поведения фронт-контроллера,
- могут быть изменение принципа хранения директорий
- контроллеров, установка других используемых по умолчанию
- маршрутизатора и диспетчера и т.д.
- </para>
- </sect2>
- </sect1>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|