[ZF-10089] Zend_Log
[zend.git] / documentation / manual / ru / module_specs / Zend_Application-TheoryOfOperation.xml
blob55820012804bc430a6c3cb1be7ed998507f65043
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!-- Reviewed: no -->
3 <sect1 id="zend.application.theory-of-operation">
4     <title>Теоретические основы работы с Zend_Application</title>
6     <para>
7         Получение сконфигурированного <acronym>MVC</acronym>-приложения,
8         готового к обработке запроса,
9         требует наличия дополнительного кода, объем которого зависит от
10         используемого функционала:
11         установка соединения с базой данных, конфигурирование видов и
12         их помощников, конфигурирование макетов (layouts), регистрация плагинов,
13         регистрация помощников действий и так далее.
14     </para>
16     <para>
17         Кроме того, вы можете захотеть повторно использовать один и тот же код
18         для загрузки тестов, сервисных скриптов, скриптов, предназначенных
19         для запуска через крон.
20         Можно просто добавлять свой скрипт загрузки, но часто встречаются
21         инициализации, зависящие от окружения - например, для
22         запуска через крон <acronym>MVC</acronym> может быть лишним, а для
23         сервисного скрипта может быть достаточно только слоя баз данных.
24     </para>
26     <para>
27         <classname>Zend_Application</classname> облегчает управление начальной
28         загрузкой и способствует повторному использованию путем инкапсуляции
29         загрузки в соответствии с парадигмой <acronym>ООП</acronym>.
30     </para>
32     <para>
33         <classname>Zend_Application</classname> состоит из трех областей:
34     </para>
36     <itemizedlist>
37         <listitem>
38             <para>
39                 <classname>Zend_Application</classname>: загружает окружение
40                 <acronym>PHP</acronym>, включая include_paths и автозагрузку
41                 (autoloading), инстанцирует запрошенный загрузочный класс.
42             </para>
43         </listitem>
44         <listitem>
45             <para>
46                 <classname>Zend_Application_Bootstrap</classname>: предоставляет
47                 интерфейсы для загрузочных классов.
48                 <classname>Zend_Application_Bootstrap_Bootstrap</classname>
49                 предоставляет общий функционал, удовлетворяющий большинство
50                 нужд по начальной загрузке, включающие в себя алгоритмы проверки
51                 зависимостей и возможность загрузки ресурсов по требованию.
52             </para>
53         </listitem>
54         <listitem>
55             <para>
56                 <classname>Zend_Application_Resource</classname> предоставляет
57                 интерфейс для стандартных ресурсов загрузки,
58                 которые могут быть загружены по требованию через экземпляр
59                 загрузочного класса, и несколько реализаций ресурсов,
60                 используемых по умолчанию.
61             </para>
62         </listitem>
63     </itemizedlist>
65     <para>
66         Разработчики могут создавать загрузочный класс для приложения,
67         расширяя <classname>Zend_Application_Bootstrap_Bootstrap</classname>
68         или, как минимум, реализуя интерфейс
69         <classname>Zend_Application_Bootstrap_Bootstrapper</classname>.
70         Входная точка (например, <filename>public/index.php</filename>)
71         будет загружать <classname>Zend_Application</classname> и
72         инстанцировать его путем передачи:
73     </para>
75     <itemizedlist>
76         <listitem>
77             <para>
78                 Текущего окружения
79             </para>
80         </listitem>
81         <listitem>
82             <para>
83                 Опций для загрузки
84             </para>
85         </listitem>
86     </itemizedlist>
88     <para>
89         Опции загрузки включают в себя путь к файлу, содержащему в себе
90         загрузочный класс и, опционально:
91     </para>
93     <itemizedlist>
94         <listitem>
95             <para>
96                 Любые дополнительные пути для добавления в include_path
97             </para>
98         </listitem>
99         <listitem>
100             <para>
101                 Любые дополнительные пространства имен автозагрузки,
102                 которые требуется зарегистрировать
103             </para>
104         </listitem>
105         <listitem>
106             <para>
107                 Любые установки <filename>php.ini</filename> для инициализации
108             </para>
109         </listitem>
110         <listitem>
111             <para>
112                 Имя класса загрузки (если используется имя, отличное от
113                 "Bootstrap")
114             </para>
115         </listitem>
116         <listitem>
117             <para>
118                 Пары префикс-путь для ресурсов
119             </para>
120         </listitem>
121         <listitem>
122             <para>
123                 Любые ресурсы для использования (указываются через имя класса
124                 или их короткое имя)
125             </para>
126         </listitem>
127         <listitem>
128             <para>
129                 Дополнительный путь к загружаемому конфигурационному файлу
130             </para>
131         </listitem>
132         <listitem>
133             <para>
134                 Дополнительные опции конфигурации
135             </para>
136         </listitem>
137     </itemizedlist>
139     <para>
140         Опции могут быть массивом, объектом <classname>Zend_Config</classname>
141         или путью к конфигурационному файлу.
142     </para>
144     <sect2 id="zend.application.theory-of-operation.bootstrap">
145         <title>Начальная загрузка</title>
147         <para>
148             Второй областью отвественности компоненты
149             <classname>Zend_Application</classname> является
150             выполнение загрузки приложения. Загрузочные классы
151             должны как минимум реализовывать интерфейс
152             <classname>Zend_Application_Bootstrap_Bootstrapper</classname>,
153             который определяет следующий <acronym>API</acronym>:
154         </para>
156         <programlisting language="php"><![CDATA[
157 interface Zend_Application_Bootstrap_Bootstrapper
159     public function __construct($application);
160     public function setOptions(array $options);
161     public function getApplication();
162     public function getEnvironment();
163     public function getClassResources();
164     public function getClassResourceNames();
165     public function bootstrap($resource = null);
166     public function run();
168 ]]></programlisting>
170         <para>
171             Этот API позволяет классу загрузки принимать окружение
172             и конфигурацию из объекта приложения, определять ресурсы,
173             за загрузку которых он отвечает, выполнять загрузку и запуск
174             приложения.
175         </para>
177         <para>
178             Вы можете сами реализовывать этот интерфейс, расширять
179             <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname>
180             или использовать
181             <classname>Zend_Application_Bootstrap_Bootstrap</classname>.
182         </para>
184         <para>
185             Кроме этого функционала есть и другие требующие внимания области,
186             с которыми вы должны ознакомиться.
187         </para>
189         <sect3 id="zend.application.theory-of-operation.bootstrap.resource-methods">
190             <title>Методы ресурсов</title>
192             <para>
193                 <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname>
194                 предоставляет простое соглашение для определения
195                 методов ресурсов. Любой защищенный метод с именем,
196                 начинающимся с <emphasis>_init</emphasis>, будет считаться
197                 методом ресурса.
198             </para>
200             <para>
201                 Для того, чтобы запустить один метод ресурса, вызывайте
202                 метод <methodname>bootstrap()</methodname> с именем ресурса в
203                 качестве аргумента. Именем ресурса будет имя метода без префикса
204                 <emphasis>_init</emphasis>.
205             </para>
207             <para>
208                 Для того, чтобы запустить несколько методов ресурсов,
209                 передавайте массив имен. А для того, чтобы запустить
210                 все методы ресурсов, вызывайте метод без аргументов.
211             </para>
213             <para>
214                 Возьмем следующий загрузочный класс:
215             </para>
217             <programlisting language="php"><![CDATA[
218 class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
220     protected function _initFoo()
221     {
222         // ...
223     }
225     protected function _initBar()
226     {
227         // ...
228     }
230     protected function _initBaz()
231     {
232         // ...
233     }
235 ]]></programlisting>
237             <para>
238                 Для того, чтобы запустить только метод
239                 <methodname>_initFoo()</methodname>, сделайте следующее:
240             </para>
242             <programlisting language="php"><![CDATA[
243 $bootstrap->bootstrap('foo');
244 ]]></programlisting>
246             <para>
247                 Для того, чтобы запустить методы
248                 <methodname>_initFoo()</methodname> и
249                 <methodname>_initBar()</methodname>, сделайте следующее:
250             </para>
252             <programlisting language="php"><![CDATA[
253 $bootstrap->bootstrap(array('foo', 'bar'));
254 ]]></programlisting>
256             <para>
257                 Для того, чтобы запустить все методы ресурсов,
258                 используйте <methodname>bootstrap()</methodname> без аргументов:
259             </para>
261             <programlisting language="php"><![CDATA[
262 $bootstrap->bootstrap();
263 ]]></programlisting>
264         </sect3>
266         <sect3 id="zend.application.theory-of-operation.bootstrap.resource-plugins">
267             <title>Загрузки, использующие плагины ресурсов</title>
269             <para>
270                 Для того, чтобы вы могли сделать свои загрузки более пригодными
271                 для повторного использования, мы реализовали возможность
272                 помещать свои ресурсы в классы-плагины ресурсов.
273                 Это позволит вам легко комбинировать ресурсы, используя
274                 конфигурацию.
275                 Ниже будет описание того, <link
276                     linkend="zend.application.theory-of-operation.resources">как
277                     создавать ресурсы</link>, в данном разделе мы только
278                 покажем, как использовать их.
279             </para>
281             <para>
282                 Если ваша загрузка должна поддерживать
283                 плагины ресурсов, то вам нужно реализовать дополнительный
284                 интерфейс
285                 <classname>Zend_Application_Bootstrap_ResourceBootstrapper</classname>.
286                 Этот интерфейс определяет <acronym>API</acronym> для
287                 определения местонахождения, регистрации и загрузки плагинов
288                 ресурсов:
289             </para>
291         <programlisting language="php"><![CDATA[
292 interface Zend_Application_Bootstrap_ResourceBootstrapper
294     public function registerPluginResource($resource, $options = null);
295     public function unregisterPluginResource($resource);
296     public function hasPluginResource($resource);
297     public function getPluginResource($resource);
298     public function getPluginResources();
299     public function getPluginResourceNames();
300     public function setPluginLoader(Zend_Loader_PluginLoader_Interface $loader);
301     public function getPluginLoader();
303 ]]></programlisting>
305             <para>
306                 Плагины ресурсов в основном дают возможность
307                 создавать инициализаторы ресурсов, которые могут повторно
308                 использоваться в различных приложениях.
309                 Это позволит вам поддерживать порядок в вашей действующей
310                 загрузке и внедрять новые ресурсы без
311                 необходимости внесения изменений в собственно загрузке.
312             </para>
314             <para>
315                 <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname>
316                 (и, следовательно, наследующий от него класс
317                 <classname>Zend_Application_Bootstrap_Bootstrap</classname>)
318                 реализуют этот интерфейс, позволяя вам использовать
319                 плагины ресурсов.
320             </para>
322             <para>
323                 Для того, чтобы использовать плагины ресурсов, вы должны
324                 указывать их в опциях, передаваемых объектам приложения и/или
325                 загрузки. Эти опции могут указываться через конфигурационный
326                 файл или передаваться вручную.
327                 Опции будут массивом пар ключ/опции, где ключом является
328                 имя ресурса. Именем ресурса будет часть строки, следующая
329                 после префикса класса. Например,
330                 ресурсы, поставляемые c Zend Framework'ом, имеют префикс класса
331                 "<classname>Zend_Application_Resource_</classname>", все, что
332                 следует за ним, будет именем ресурса. Например:
333             </para>
335             <programlisting language="php"><![CDATA[
336 $application = new Zend_Application(APPLICATION_ENV, array(
337     'resources' => array(
338         'FrontController' => array(
339             'controllerDirectory' => APPLICATION_PATH . '/controllers',
340         ),
341     ),
343 ]]></programlisting>
345             <para>
346                 Это означает, что должен использоваться ресурс
347                 "FrontController" с указанными опциями.
348             </para>
350             <para>
351                 Если вы планируете писать собственные плагины ресурсов
352                 либо добавить сторонние, то нужно будет указать вашей
353                 загрузке, где их искать.
354                 Внутри себя загрузка использует
355                 <classname>Zend_Loader_PluginLoader</classname>, поэтому
356                 достаточно указать префикс класса и путь к директории с
357                 плагинами ресурсов.
358             </para>
360             <para>
361                 Для примера предположим, что вы имеете свои плагины ресурсов
362                 в директории <filename>APPLICATION_PATH/resources/</filename>,
363                 и они используют общий префикс
364                 <classname>My_Resource</classname>.
365                 Вы можете передать эту информацию объекту приложения так,
366                 как показано ниже:
367             </para>
369             <programlisting language="php"><![CDATA[
370 $application = new Zend_Application(APPLICATION_ENV, array(
371     'pluginPaths' => array(
372         'My_Resource' => APPLICATION_PATH . '/resources/',
373     ),
374     'resources' => array(
375         'FrontController' => array(
376             'controllerDirectory' => APPLICATION_PATH . '/controllers',
377         ),
378     ),
380 ]]></programlisting>
382             <para>
383                 После этого вы можете использовать ресурсы из этой директории.
384             </para>
386             <para>
387                 Так же, как и в случае с методами ресурсов, вы используете
388                 метод <methodname>bootstrap()</methodname> для выполнения
389                 плагинов ресурсов.
390                 И точно так же вы можете указывать один плагин ресурса,
391                 несколько плагинов ресурсов (через массив), либо запускать все плагины
392                 сразу. Кроме того, вы можете комбинировать их с методами
393                 ресурсов.
394             </para>
396             <programlisting language="php"><![CDATA[
397 // Выполнить один:
398 $bootstrap->bootstrap('FrontController');
400 // Выполнить несколько:
401 $bootstrap->bootstrap(array('FrontController', 'Foo'));
403 // Выполнить все ресурсы и плагины:
404 $bootstrap->bootstrap();
405 ]]></programlisting>
406         </sect3>
408         <sect3 id="zend.application.theory-of-operation.bootstrap.registry">
409             <title>Реестр ресурсов</title>
411             <para>
412                 Большинство, если не все, методы и плагины ресурсов
413                 будут инициализировать объекты, и во многих случаях эти
414                 объекты будут нужны где-то еще в приложении.
415                 Как получить к ним доступ?
416             </para>
418             <para>
419                 <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname>
420                 предоставляет локальный реестр для этих объектов.
421                 Для того, чтобы сохранять свои объекты в нем, просто возвращайте
422                 их из своего ресурса.
423             </para>
425             <para>
426                 Для большей гибкости этот реестр внутри себя ссылается на
427                 "контейнеры";
428                 единственное требование состоит в том, чтобы это был объект.
429                 Ресурсы регистрируются как свойства, имена которых совпадают
430                 с именами ресурсов.
431                 По умолчанию используется экземпляр
432                 <classname>Zend_Registry</classname>, но вы можете при
433                 желании указывать любой другой объект.
434                 Для работы с контейнерами могут использоваться методы
435                 <methodname>setContainer()</methodname> и
436                 <methodname>getContainer()</methodname>.
437                 Метод <methodname>getResource($resource)</methodname>
438                 может использоваться для извлечения ресурса из контейнера,
439                 а <methodname>hasResource($resource)</methodname> - для
440                 проверки того, был ли зарегистрирован данный ресурс.
441             </para>
443             <para>
444                 Для примера рассмотрим базовый ресурс вида:
445             </para>
447             <programlisting language="php"><![CDATA[
448 class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
450     protected function _initView()
451     {
452         $view = new Zend_View();
453         // дальнейшая инициализация...
455         return $view;
456     }
458 ]]></programlisting>
460             <para>
461                 Вы можете затем проверять его наличие и/или извлекать его
462                 как показано ниже:
463             </para>
465             <programlisting language="php"><![CDATA[
466 // Использование пары has/getResource()
467 if ($bootstrap->hasResource('view')) {
468     $view = $bootstrap->getResource('view');
471 // Через контейнер:
472 $container = $bootstrap->getContainer();
473 if (isset($container->view)) {
474     $view = $container->view;
476 ]]></programlisting>
478             <para>
479                 Следует заметить, что реестр и контейнер не являются
480                 глобальными. Это означает, что вам нужно иметь доступ к объекту
481                 загрузки с тем, чтобы можно было извлекать ресурсы.
482                 <classname>Zend_Application_Bootstrap_Bootstrap</classname>
483                 предоставляет некоторые удобства для этого:
484                 во время выполнения <methodname>run()</methodname> он
485                 регистрирует себя в качестве параметра "bootstrap"
486                 во фронт-контроллере, это позволяет извлекать его внутри
487                 маршрутизатора, диспетчера, плагинов и контроллеров действий.
488             </para>
490             <para>
491                 Например, если вы хотите внутри своего контроллера действий
492                 получить доступ к ресурсу вида из примеров выше, то
493                 можете сделать следующее:
494             </para>
496             <programlisting language="php"><![CDATA[
497 class FooController extends Zend_Controller_Action
499     public function init()
500     {
501         $bootstrap = $this->getInvokeArg('bootstrap');
502         $view = $bootstrap->getResource('view');
503         // ...
504     }
506 ]]></programlisting>
507         </sect3>
509         <sect3 id="zend.application.theory-of-operation.bootstrap.dependency-tracking">
510             <title>Отслеживание зависимостей</title>
512             <para>
513                 Кроме выполнения методов и плагинов ресурсов,
514                 необходимо также гарантировать, что они выполняются один и
515                 только один раз. Они предназначены для загрузки приложения,
516                 и выполнение их больше одного раза может привести к
517                 непроизводительному расходованию ресурсов.
518             </para>
520             <para>
521                 В то же время некоторые ресурсы могут зависеть от других и
522                 требовать их предварительной загрузки до начала своего
523                 выполнения.
524                 Для решения этих двух проблем
525                 <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname>
526                 предоставляет простой и эффективный механизм для отслеживания
527                 зависимостей.
528             </para>
530             <para>
531                 Как было сказано ранее, все ресурсы - как методы, так и
532                 плагины, - загружаются путем вызова
533                 <methodname>bootstrap($resource)</methodname>, где
534                 <varname>$resource</varname> является именем ресурса или
535                 массивом ресурсов. Если параметр <varname>$resource</varname>
536                 опущен, то это означает, что все ресурсы должны быть запущены.
537             </para>
539             <para>
540                 Если ресурс зависит от других ресурсов, то он должен вызывать
541                 метод <methodname>bootstrap()</methodname> в своем коде
542                 для обеспечения выполнения этих ресурсов.
543                 Последующие вызовы для этих ресурсов будут проигнорированы.
544             </para>
546             <para>
547                 В методе ресурса такой вызов будет выглядеть следующим образом:
548             </para>
550             <programlisting language="php"><![CDATA[
551 class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
553     protected function _initRequest()
554     {
555         // Обеспечение инициализации контроллера
556         $this->bootstrap('FrontController');
558         // Извлечение фронт-контроллера из реестра загрузки
559         $front = $this->getResource('FrontController');
561         $request = new Zend_Controller_Request_Http();
562         $request->setBaseUrl('/foo');
563         $front->setRequest($request);
565         // Обеспечение сохранения запроса в реестре загрузки
566         return $request;
567     }
569 ]]></programlisting>
570         </sect3>
571     </sect2>
573     <sect2 id="zend.application.theory-of-operation.resources">
574         <title>Плагины ресурсов</title>
576         <para>
577             <link linkend="zend.application.theory-of-operation.bootstrap.resource-plugins">Как
578                 было сказано ранее</link>,
579             хорошим способом создания повторно используемых ресурсов загрузки
580             и выделения кода в отдельные классы является
581             использование плагинов ресурсов.
582             Хотя Zend Framework поставляется с набором стандартных плагинов
583             ресурсов, замысел состоит в том, что разработчики должны
584             писать собственные плагины с целью инкапсуляции собственного
585             кода, предназначенного для инициализации.
586         </para>
588         <para>
589             Ресурсы должны только реализовывать интерфейс
590             <classname>Zend_Application_Resource_Resource</classname> или, что
591             является более простым вариантом, расширять абстрактный класс
592             <classname>Zend_Application_Resource_ResourceAbstract</classname>.
593             Базовый интерфейс довольно прост:
594         </para>
596         <programlisting language="php"><![CDATA[
597 interface Zend_Application_Resource_Resource
599     public function __construct($options = null);
600     public function setBootstrap(
601         Zend_Application_Bootstrap_Bootstrapper $bootstrap
602     );
603     public function getBootstrap();
604     public function setOptions(array $options);
605     public function getOptions();
606     public function init();
608 ]]></programlisting>
610         <para>
611             Он определяет только, что ресурс должен принимать опции
612             через конструктор, иметь механизмы для установки/получения
613             опций, механизмы для установки/получения объекта загрузочного класса
614             и метод инициализации.
615         </para>
617         <para>
618             Для примера предположим, что вы имеете инициализацию вида,
619             одинаковую для нескольких ваших приложений. Вы используете в
620             них одну и ту же декларацию DOCTYPE, одни и те же
621             <acronym>CSS</acronym>-стили, скрипты JavaScript,
622             а также хотите иметь возможность задавать базовый заголовок
623             документа через конфигурацию.
624             Ресурс, выполняющий такую инициализацию, может выглядеть следующим
625             образом:
626         </para>
628         <programlisting language="php"><![CDATA[
629 class My_Resource_View extends Zend_Application_Resource_ResourceAbstract
631     protected $_view;
633     public function init()
634     {
635         // Возвращает вид, таким образом, он будет сохранен в реестре
636         return $this->getView();
637     }
639     public function getView()
640     {
641         if (null === $this->_view) {
642             $options = $this->getOptions();
643             $title   = '';
644             if (array_key_exists('title', $options)) {
645                 $title = $options['title'];
646                 unset($options['title']);
647             }
649             $view = new Zend_View($options);
650             $view->doctype('XHTML1_STRICT');
651             $view->headTitle($title);
652             $view->headLink()->appendStylesheet('/css/site.css');
653             $view->headScript()->appendfile('/js/analytics.js');
655             $viewRenderer =
656                 Zend_Controller_Action_HelperBroker::getStaticHelper(
657                     'ViewRenderer'
658                 );
659             $viewRenderer->setView($view);
661             $this->_view = $view;
662         }
663         return $this->_view;
664     }
666 ]]></programlisting>
668         <para>
669             Зарегистрировав путь к этому плагину ресурса, вы можете
670             использовать его в своем приложении. Сверх того, благодаря
671             использованию загрузчика плагинов вы эффективно
672             переопределите идущий в поставке плагин ресурса "View", тем самым
673             обеспечивая использование своего плагина вместо него.
674         </para>
675     </sect2>
676 </sect1>