| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- Reviewed: no -->
- <sect1 id="zend.application.theory-of-operation">
- <title>Теоретические основы работы с Zend_Application</title>
- <para>
- Получение сконфигурированного <acronym>MVC</acronym>-приложения,
- готового к обработке запроса,
- требует наличия дополнительного кода, объем которого зависит от
- используемого функционала:
- установка соединения с базой данных, конфигурирование видов и
- их помощников, конфигурирование макетов (layouts), регистрация плагинов,
- регистрация помощников действий и так далее.
- </para>
- <para>
- Кроме того, вы можете захотеть повторно использовать один и тот же код
- для загрузки тестов, сервисных скриптов, скриптов, предназначенных
- для запуска через крон.
- Можно просто добавлять свой скрипт загрузки, но часто встречаются
- инициализации, зависящие от окружения - например, для
- запуска через крон <acronym>MVC</acronym> может быть лишним, а для
- сервисного скрипта может быть достаточно только слоя баз данных.
- </para>
- <para>
- <classname>Zend_Application</classname> облегчает управление начальной
- загрузкой и способствует повторному использованию путем инкапсуляции
- загрузки в соответствии с парадигмой <acronym>ООП</acronym>.
- </para>
- <para>
- <classname>Zend_Application</classname> состоит из трех областей:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <classname>Zend_Application</classname>: загружает окружение
- <acronym>PHP</acronym>, включая include_paths и автозагрузку
- (autoloading), инстанцирует запрошенный загрузочный класс.
- </para>
- </listitem>
- <listitem>
- <para>
- <classname>Zend_Application_Bootstrap</classname>: предоставляет
- интерфейсы для загрузочных классов.
- <classname>Zend_Application_Bootstrap_Bootstrap</classname>
- предоставляет общий функционал, удовлетворяющий большинство
- нужд по начальной загрузке, включающие в себя алгоритмы проверки
- зависимостей и возможность загрузки ресурсов по требованию.
- </para>
- </listitem>
- <listitem>
- <para>
- <classname>Zend_Application_Resource</classname> предоставляет
- интерфейс для стандартных ресурсов загрузки,
- которые могут быть загружены по требованию через экземпляр
- загрузочного класса, и несколько реализаций ресурсов,
- используемых по умолчанию.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- Разработчики могут создавать загрузочный класс для приложения,
- расширяя <classname>Zend_Application_Bootstrap_Bootstrap</classname>
- или, как минимум, реализуя интерфейс
- <classname>Zend_Application_Bootstrap_Bootstrapper</classname>.
- Входная точка (например, <filename>public/index.php</filename>)
- будет загружать <classname>Zend_Application</classname> и
- инстанцировать его путем передачи:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- Текущего окружения
- </para>
- </listitem>
- <listitem>
- <para>
- Опций для загрузки
- </para>
- </listitem>
- </itemizedlist>
- <para>
- Опции загрузки включают в себя путь к файлу, содержащему в себе
- загрузочный класс и, опционально:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- Любые дополнительные пути для добавления в include_path
- </para>
- </listitem>
- <listitem>
- <para>
- Любые дополнительные пространства имен автозагрузки,
- которые требуется зарегистрировать
- </para>
- </listitem>
- <listitem>
- <para>
- Любые установки <filename>php.ini</filename> для инициализации
- </para>
- </listitem>
- <listitem>
- <para>
- Имя класса загрузки (если используется имя, отличное от
- "Bootstrap")
- </para>
- </listitem>
- <listitem>
- <para>
- Пары префикс-путь для ресурсов
- </para>
- </listitem>
- <listitem>
- <para>
- Любые ресурсы для использования (указываются через имя класса
- или их короткое имя)
- </para>
- </listitem>
- <listitem>
- <para>
- Дополнительный путь к загружаемому конфигурационному файлу
- </para>
- </listitem>
- <listitem>
- <para>
- Дополнительные опции конфигурации
- </para>
- </listitem>
- </itemizedlist>
- <para>
- Опции могут быть массивом, объектом <classname>Zend_Config</classname>
- или путью к конфигурационному файлу.
- </para>
- <sect2 id="zend.application.theory-of-operation.bootstrap">
- <title>Начальная загрузка</title>
- <para>
- Второй областью отвественности компоненты
- <classname>Zend_Application</classname> является
- выполнение загрузки приложения. Загрузочные классы
- должны как минимум реализовывать интерфейс
- <classname>Zend_Application_Bootstrap_Bootstrapper</classname>,
- который определяет следующий <acronym>API</acronym>:
- </para>
- <programlisting language="php"><![CDATA[
- interface Zend_Application_Bootstrap_Bootstrapper
- {
- public function __construct($application);
- public function setOptions(array $options);
- public function getApplication();
- public function getEnvironment();
- public function getClassResources();
- public function getClassResourceNames();
- public function bootstrap($resource = null);
- public function run();
- }
- ]]></programlisting>
- <para>
- Этот API позволяет классу загрузки принимать окружение
- и конфигурацию из объекта приложения, определять ресурсы,
- за загрузку которых он отвечает, выполнять загрузку и запуск
- приложения.
- </para>
- <para>
- Вы можете сами реализовывать этот интерфейс, расширять
- <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname>
- или использовать
- <classname>Zend_Application_Bootstrap_Bootstrap</classname>.
- </para>
- <para>
- Кроме этого функционала есть и другие требующие внимания области,
- с которыми вы должны ознакомиться.
- </para>
- <sect3 id="zend.application.theory-of-operation.bootstrap.resource-methods">
- <title>Методы ресурсов</title>
- <para>
- <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname>
- предоставляет простое соглашение для определения
- методов ресурсов. Любой защищенный метод с именем,
- начинающимся с <emphasis>_init</emphasis>, будет считаться
- методом ресурса.
- </para>
- <para>
- Для того, чтобы запустить один метод ресурса, вызывайте
- метод <methodname>bootstrap()</methodname> с именем ресурса в
- качестве аргумента. Именем ресурса будет имя метода без префикса
- <emphasis>_init</emphasis>.
- </para>
- <para>
- Для того, чтобы запустить несколько методов ресурсов,
- передавайте массив имен. А для того, чтобы запустить
- все методы ресурсов, вызывайте метод без аргументов.
- </para>
- <para>
- Возьмем следующий загрузочный класс:
- </para>
- <programlisting language="php"><![CDATA[
- class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
- {
- protected function _initFoo()
- {
- // ...
- }
- protected function _initBar()
- {
- // ...
- }
- protected function _initBaz()
- {
- // ...
- }
- }
- ]]></programlisting>
- <para>
- Для того, чтобы запустить только метод
- <methodname>_initFoo()</methodname>, сделайте следующее:
- </para>
- <programlisting language="php"><![CDATA[
- $bootstrap->bootstrap('foo');
- ]]></programlisting>
- <para>
- Для того, чтобы запустить методы
- <methodname>_initFoo()</methodname> и
- <methodname>_initBar()</methodname>, сделайте следующее:
- </para>
- <programlisting language="php"><![CDATA[
- $bootstrap->bootstrap(array('foo', 'bar'));
- ]]></programlisting>
- <para>
- Для того, чтобы запустить все методы ресурсов,
- используйте <methodname>bootstrap()</methodname> без аргументов:
- </para>
- <programlisting language="php"><![CDATA[
- $bootstrap->bootstrap();
- ]]></programlisting>
- </sect3>
- <sect3 id="zend.application.theory-of-operation.bootstrap.resource-plugins">
- <title>Загрузки, использующие плагины ресурсов</title>
- <para>
- Для того, чтобы вы могли сделать свои загрузки более пригодными
- для повторного использования, мы реализовали возможность
- помещать свои ресурсы в классы-плагины ресурсов.
- Это позволит вам легко комбинировать ресурсы, используя
- конфигурацию.
- Ниже будет описание того, <link
- linkend="zend.application.theory-of-operation.resources">как
- создавать ресурсы</link>, в данном разделе мы только
- покажем, как использовать их.
- </para>
- <para>
- Если ваша загрузка должна поддерживать
- плагины ресурсов, то вам нужно реализовать дополнительный
- интерфейс
- <classname>Zend_Application_Bootstrap_ResourceBootstrapper</classname>.
- Этот интерфейс определяет <acronym>API</acronym> для
- определения местонахождения, регистрации и загрузки плагинов
- ресурсов:
- </para>
- <programlisting language="php"><![CDATA[
- interface Zend_Application_Bootstrap_ResourceBootstrapper
- {
- public function registerPluginResource($resource, $options = null);
- public function unregisterPluginResource($resource);
- public function hasPluginResource($resource);
- public function getPluginResource($resource);
- public function getPluginResources();
- public function getPluginResourceNames();
- public function setPluginLoader(Zend_Loader_PluginLoader_Interface $loader);
- public function getPluginLoader();
- }
- ]]></programlisting>
- <para>
- Плагины ресурсов в основном дают возможность
- создавать инициализаторы ресурсов, которые могут повторно
- использоваться в различных приложениях.
- Это позволит вам поддерживать порядок в вашей действующей
- загрузке и внедрять новые ресурсы без
- необходимости внесения изменений в собственно загрузке.
- </para>
- <para>
- <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname>
- (и, следовательно, наследующий от него класс
- <classname>Zend_Application_Bootstrap_Bootstrap</classname>)
- реализуют этот интерфейс, позволяя вам использовать
- плагины ресурсов.
- </para>
- <para>
- Для того, чтобы использовать плагины ресурсов, вы должны
- указывать их в опциях, передаваемых объектам приложения и/или
- загрузки. Эти опции могут указываться через конфигурационный
- файл или передаваться вручную.
- Опции будут массивом пар ключ/опции, где ключом является
- имя ресурса. Именем ресурса будет часть строки, следующая
- после префикса класса. Например,
- ресурсы, поставляемые c Zend Framework'ом, имеют префикс класса
- "<classname>Zend_Application_Resource_</classname>", все, что
- следует за ним, будет именем ресурса. Например:
- </para>
- <programlisting language="php"><![CDATA[
- $application = new Zend_Application(APPLICATION_ENV, array(
- 'resources' => array(
- 'FrontController' => array(
- 'controllerDirectory' => APPLICATION_PATH . '/controllers',
- ),
- ),
- ));
- ]]></programlisting>
- <para>
- Это означает, что должен использоваться ресурс
- "FrontController" с указанными опциями.
- </para>
- <para>
- Если вы планируете писать собственные плагины ресурсов
- либо добавить сторонние, то нужно будет указать вашей
- загрузке, где их искать.
- Внутри себя загрузка использует
- <classname>Zend_Loader_PluginLoader</classname>, поэтому
- достаточно указать префикс класса и путь к директории с
- плагинами ресурсов.
- </para>
- <para>
- Для примера предположим, что вы имеете свои плагины ресурсов
- в директории <filename>APPLICATION_PATH/resources/</filename>,
- и они используют общий префикс
- <classname>My_Resource</classname>.
- Вы можете передать эту информацию объекту приложения так,
- как показано ниже:
- </para>
- <programlisting language="php"><![CDATA[
- $application = new Zend_Application(APPLICATION_ENV, array(
- 'pluginPaths' => array(
- 'My_Resource' => APPLICATION_PATH . '/resources/',
- ),
- 'resources' => array(
- 'FrontController' => array(
- 'controllerDirectory' => APPLICATION_PATH . '/controllers',
- ),
- ),
- ));
- ]]></programlisting>
- <para>
- После этого вы можете использовать ресурсы из этой директории.
- </para>
- <para>
- Так же, как и в случае с методами ресурсов, вы используете
- метод <methodname>bootstrap()</methodname> для выполнения
- плагинов ресурсов.
- И точно так же вы можете указывать один плагин ресурса,
- несколько плагинов ресурсов (через массив), либо запускать все плагины
- сразу. Кроме того, вы можете комбинировать их с методами
- ресурсов.
- </para>
- <programlisting language="php"><![CDATA[
- // Выполнить один:
- $bootstrap->bootstrap('FrontController');
- // Выполнить несколько:
- $bootstrap->bootstrap(array('FrontController', 'Foo'));
- // Выполнить все ресурсы и плагины:
- $bootstrap->bootstrap();
- ]]></programlisting>
- </sect3>
- <sect3 id="zend.application.theory-of-operation.bootstrap.registry">
- <title>Реестр ресурсов</title>
- <para>
- Большинство, если не все, методы и плагины ресурсов
- будут инициализировать объекты, и во многих случаях эти
- объекты будут нужны где-то еще в приложении.
- Как получить к ним доступ?
- </para>
- <para>
- <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname>
- предоставляет локальный реестр для этих объектов.
- Для того, чтобы сохранять свои объекты в нем, просто возвращайте
- их из своего ресурса.
- </para>
- <para>
- Для большей гибкости этот реестр внутри себя ссылается на
- "контейнеры";
- единственное требование состоит в том, чтобы это был объект.
- Ресурсы регистрируются как свойства, имена которых совпадают
- с именами ресурсов.
- По умолчанию используется экземпляр
- <classname>Zend_Registry</classname>, но вы можете при
- желании указывать любой другой объект.
- Для работы с контейнерами могут использоваться методы
- <methodname>setContainer()</methodname> и
- <methodname>getContainer()</methodname>.
- Метод <methodname>getResource($resource)</methodname>
- может использоваться для извлечения ресурса из контейнера,
- а <methodname>hasResource($resource)</methodname> - для
- проверки того, был ли зарегистрирован данный ресурс.
- </para>
- <para>
- Для примера рассмотрим базовый ресурс вида:
- </para>
- <programlisting language="php"><![CDATA[
- class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
- {
- protected function _initView()
- {
- $view = new Zend_View();
- // дальнейшая инициализация...
- return $view;
- }
- }
- ]]></programlisting>
- <para>
- Вы можете затем проверять его наличие и/или извлекать его
- как показано ниже:
- </para>
- <programlisting language="php"><![CDATA[
- // Использование пары has/getResource()
- if ($bootstrap->hasResource('view')) {
- $view = $bootstrap->getResource('view');
- }
- // Через контейнер:
- $container = $bootstrap->getContainer();
- if (isset($container->view)) {
- $view = $container->view;
- }
- ]]></programlisting>
- <para>
- Следует заметить, что реестр и контейнер не являются
- глобальными. Это означает, что вам нужно иметь доступ к объекту
- загрузки с тем, чтобы можно было извлекать ресурсы.
- <classname>Zend_Application_Bootstrap_Bootstrap</classname>
- предоставляет некоторые удобства для этого:
- во время выполнения <methodname>run()</methodname> он
- регистрирует себя в качестве параметра "bootstrap"
- во фронт-контроллере, это позволяет извлекать его внутри
- маршрутизатора, диспетчера, плагинов и контроллеров действий.
- </para>
- <para>
- Например, если вы хотите внутри своего контроллера действий
- получить доступ к ресурсу вида из примеров выше, то
- можете сделать следующее:
- </para>
- <programlisting language="php"><![CDATA[
- class FooController extends Zend_Controller_Action
- {
- public function init()
- {
- $bootstrap = $this->getInvokeArg('bootstrap');
- $view = $bootstrap->getResource('view');
- // ...
- }
- }
- ]]></programlisting>
- </sect3>
- <sect3 id="zend.application.theory-of-operation.bootstrap.dependency-tracking">
- <title>Отслеживание зависимостей</title>
- <para>
- Кроме выполнения методов и плагинов ресурсов,
- необходимо также гарантировать, что они выполняются один и
- только один раз. Они предназначены для загрузки приложения,
- и выполнение их больше одного раза может привести к
- непроизводительному расходованию ресурсов.
- </para>
- <para>
- В то же время некоторые ресурсы могут зависеть от других и
- требовать их предварительной загрузки до начала своего
- выполнения.
- Для решения этих двух проблем
- <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname>
- предоставляет простой и эффективный механизм для отслеживания
- зависимостей.
- </para>
- <para>
- Как было сказано ранее, все ресурсы - как методы, так и
- плагины, - загружаются путем вызова
- <methodname>bootstrap($resource)</methodname>, где
- <varname>$resource</varname> является именем ресурса или
- массивом ресурсов. Если параметр <varname>$resource</varname>
- опущен, то это означает, что все ресурсы должны быть запущены.
- </para>
- <para>
- Если ресурс зависит от других ресурсов, то он должен вызывать
- метод <methodname>bootstrap()</methodname> в своем коде
- для обеспечения выполнения этих ресурсов.
- Последующие вызовы для этих ресурсов будут проигнорированы.
- </para>
- <para>
- В методе ресурса такой вызов будет выглядеть следующим образом:
- </para>
- <programlisting language="php"><![CDATA[
- class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
- {
- protected function _initRequest()
- {
- // Обеспечение инициализации контроллера
- $this->bootstrap('FrontController');
- // Извлечение фронт-контроллера из реестра загрузки
- $front = $this->getResource('FrontController');
- $request = new Zend_Controller_Request_Http();
- $request->setBaseUrl('/foo');
- $front->setRequest($request);
- // Обеспечение сохранения запроса в реестре загрузки
- return $request;
- }
- }
- ]]></programlisting>
- </sect3>
- </sect2>
- <sect2 id="zend.application.theory-of-operation.resources">
- <title>Плагины ресурсов</title>
- <para>
- <link linkend="zend.application.theory-of-operation.bootstrap.resource-plugins">Как
- было сказано ранее</link>,
- хорошим способом создания повторно используемых ресурсов загрузки
- и выделения кода в отдельные классы является
- использование плагинов ресурсов.
- Хотя Zend Framework поставляется с набором стандартных плагинов
- ресурсов, замысел состоит в том, что разработчики должны
- писать собственные плагины с целью инкапсуляции собственного
- кода, предназначенного для инициализации.
- </para>
- <para>
- Ресурсы должны только реализовывать интерфейс
- <classname>Zend_Application_Resource_Resource</classname> или, что
- является более простым вариантом, расширять абстрактный класс
- <classname>Zend_Application_Resource_ResourceAbstract</classname>.
- Базовый интерфейс довольно прост:
- </para>
- <programlisting language="php"><![CDATA[
- interface Zend_Application_Resource_Resource
- {
- public function __construct($options = null);
- public function setBootstrap(
- Zend_Application_Bootstrap_Bootstrapper $bootstrap
- );
- public function getBootstrap();
- public function setOptions(array $options);
- public function getOptions();
- public function init();
- }
- ]]></programlisting>
- <para>
- Он определяет только, что ресурс должен принимать опции
- через конструктор, иметь механизмы для установки/получения
- опций, механизмы для установки/получения объекта загрузочного класса
- и метод инициализации.
- </para>
- <para>
- Для примера предположим, что вы имеете инициализацию вида,
- одинаковую для нескольких ваших приложений. Вы используете в
- них одну и ту же декларацию DOCTYPE, одни и те же
- <acronym>CSS</acronym>-стили, скрипты JavaScript,
- а также хотите иметь возможность задавать базовый заголовок
- документа через конфигурацию.
- Ресурс, выполняющий такую инициализацию, может выглядеть следующим
- образом:
- </para>
- <programlisting language="php"><![CDATA[
- class My_Resource_View extends Zend_Application_Resource_ResourceAbstract
- {
- protected $_view;
- public function init()
- {
- // Возвращает вид, таким образом, он будет сохранен в реестре
- return $this->getView();
- }
- public function getView()
- {
- if (null === $this->_view) {
- $options = $this->getOptions();
- $title = '';
- if (array_key_exists('title', $options)) {
- $title = $options['title'];
- unset($options['title']);
- }
- $view = new Zend_View($options);
- $view->doctype('XHTML1_STRICT');
- $view->headTitle($title);
- $view->headLink()->appendStylesheet('/css/site.css');
- $view->headScript()->appendfile('/js/analytics.js');
- $viewRenderer =
- Zend_Controller_Action_HelperBroker::getStaticHelper(
- 'ViewRenderer'
- );
- $viewRenderer->setView($view);
- $this->_view = $view;
- }
- return $this->_view;
- }
- }
- ]]></programlisting>
- <para>
- Зарегистрировав путь к этому плагину ресурса, вы можете
- использовать его в своем приложении. Сверх того, благодаря
- использованию загрузчика плагинов вы эффективно
- переопределите идущий в поставке плагин ресурса "View", тем самым
- обеспечивая использование своего плагина вместо него.
- </para>
- </sect2>
- </sect1>
|