Zend_Application-TheoryOfOperation.xml 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- EN-Revision: 15617 -->
  3. <!-- Reviewed: no -->
  4. <sect1 id="zend.application.theory-of-operation">
  5. <title>Theorie der Funktionsweise</title>
  6. <para>
  7. Um eine MVC Anwendung zu konfigurieren und bereit zur Auslieferung zu bekommen wird ein
  8. immer größerer Anteil an Code benötigt sobald mehr Features verfügbar sind: Setzen der
  9. Datenbank, Konfiguration der View und View Helfer, Konfiguration der Layouts, Registrierung
  10. der Plugins, Registrierung der Aktion Helfer, und andere.
  11. </para>
  12. <para>
  13. Zusätzlich will man oft den gleichen Code wiederverwenden um Tests zu bootstrappen, einen
  14. Cronjob, oder ein Service Skript zu haben. Wärend es sehr einfach ist sein Bootstrap Skript
  15. einzubauen, gibt es oft Initialisierungen die abhängig sind von der Umgebung - man könnte
  16. kein MVC für einen Cronjob benötigen, oder nur den DB Layer für ein Service Skript.
  17. </para>
  18. <para>
  19. <classname>Zend_Application</classname> zielt darauf ab das alles einfacher zu machen und
  20. bietet Wiederwervendbarkeit durch die Kapselung vom Bootstrapping in OOP Paradigmen.
  21. </para>
  22. <para>
  23. <classname>Zend_Application</classname> ist in drei Bereiche geteilt:
  24. </para>
  25. <itemizedlist>
  26. <listitem>
  27. <para>
  28. <classname>Zend_Application</classname>: Lädt die PHP Umgebung, inklusive
  29. Inklude-Pfade und Autoloading, und instanziiert die benötigte Bootstrap Klasse.
  30. </para>
  31. </listitem>
  32. <listitem>
  33. <para>
  34. <classname>Zend_Application_Bootstrap</classname>: Bietet Interfaces für Bootstrap
  35. Klassen. <classname>Zend_Application_Bootstrap_Bootstrap</classname> bietet übliche
  36. Funktionalitäten für die meisten Notwendigkeiten des Bootstrappings, inklusive
  37. Angorithmen um Abhängigkeiten zu prüfen und die Möglichkeit Bootstrap Ressourcen bei
  38. Bedarf zu laden.
  39. </para>
  40. </listitem>
  41. <listitem>
  42. <para>
  43. <classname>Zend_Application_Resource</classname> bietet ein Interface für Standard
  44. Bootstrap Ressourcen die bei Bedarf von einer Bootstrap Instanz geladen werden
  45. können, sowie verschiedene standardmäßige Ressource Implementationen.
  46. </para>
  47. </listitem>
  48. </itemizedlist>
  49. <para>
  50. Entwickler erstellen eine Bootstrap Klasse für Ihre Anwendung und erweitern
  51. <classname>Zend_Application_Bootstrap_Bootstrap</classname> oder implementieren (mindestens)
  52. <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname>. Der Einstiegspunkt
  53. (z.B. <filename>public/index.php</filename>) lädt <classname>Zend_Application</classname>
  54. und initialisiert Sie, indem folgendes übergeben wird:
  55. </para>
  56. <itemizedlist>
  57. <listitem>
  58. <para>
  59. Die aktuelle Umgebung
  60. </para>
  61. </listitem>
  62. <listitem>
  63. <para>
  64. Optionen für das Bootstrapping
  65. </para>
  66. </listitem>
  67. </itemizedlist>
  68. <para>
  69. Die Bootstrap Optionen enthalten den Pfad zur Datei die die Bootstrap Klasse enthält und
  70. optional:
  71. </para>
  72. <itemizedlist>
  73. <listitem>
  74. <para>
  75. Jeden include_path der extra zu setzen ist
  76. </para>
  77. </listitem>
  78. <listitem>
  79. <para>
  80. Jeden Autoloader Namespace der zusätzlich zu registrieren ist
  81. </para>
  82. </listitem>
  83. <listitem>
  84. <para>
  85. Jede php.ini Einstellung die zu initialisieren ist
  86. </para>
  87. </listitem>
  88. <listitem>
  89. <para>
  90. Den Klassennamen für die Bootstrap Klasse (wenn diese nicht "Bootstrap" ist)
  91. </para>
  92. </listitem>
  93. <listitem>
  94. <para>
  95. Ressourcen Präfix/Pfad Paare die zu verwenden sind
  96. </para>
  97. </listitem>
  98. <listitem>
  99. <para>
  100. Jede Ressource die zu verwenden ist (durch Name der Klasse oder Kurzname)
  101. </para>
  102. </listitem>
  103. <listitem>
  104. <para>
  105. Zusätzliche Pfade zu einer Konfigurationsdatei die zu laden ist
  106. </para>
  107. </listitem>
  108. <listitem>
  109. <para>
  110. Zusätzliche Konfigurations Optionen
  111. </para>
  112. </listitem>
  113. </itemizedlist>
  114. <para>
  115. Optionen können, ein Array, ein <classname>Zend_Config</classname> Objekt, oder der Pfad zu
  116. einer Konfigurationsdatei sein.
  117. </para>
  118. <sect2 id="zend.application.theory-of-operation.bootstrap">
  119. <title>Bootstrapping</title>
  120. <para>
  121. <classname>Zend_Application</classname>'s zweites Feld der Arbeit ist die Ausführung des
  122. Bootstraps der Anwendung. Bootstraps müssen mindestens
  123. <classname>Zend_Application_Bootstrap_Bootstrapper</classname> implementieren, welches
  124. die folgende API definiert:
  125. </para>
  126. <programlisting language="php"><![CDATA[
  127. interface Zend_Application_Bootstrap_Bootstrapper
  128. {
  129. public function __construct($application);
  130. public function setOptions(array $options);
  131. public function getApplication();
  132. public function getEnvironment();
  133. public function getClassResources();
  134. public function getClassResourceNames();
  135. public function bootstrap($resource = null);
  136. public function run();
  137. }
  138. ]]></programlisting>
  139. <para>
  140. Diese API erlaubt es dem Bootstrap die Umgebung und die Konfiguration vom Objekt der
  141. Anwendung zu akzeptieren, die Ressourcen die für das Bootstrapping verantwortlich sind
  142. zu melden, und dann das Bootstrappen ausführen und die Anwendung zu starten.
  143. </para>
  144. <para>
  145. Man kann dieses Interface selbst implementieren,
  146. <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname> erweitern, oder
  147. <classname>Zend_Application_Bootstrap_Bootstrap</classname> verwenden.
  148. </para>
  149. <para>
  150. Neben dieser Funktionalität gibt es eine Anzahl anderer Gebiete von Interesse mit denen
  151. man vertraut sein sollte.
  152. </para>
  153. <sect3 id="zend.application.theory-of-operation.bootstrap.resource-methods">
  154. <title>Methoden für Ressourcen</title>
  155. <para>
  156. Die Implementation von
  157. <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname> bietet eine
  158. einfache Konvention für die Definition von Methoden für Ressourcen Klassen. Jede
  159. geschützte Methode (protected), deren Name mit <code>_init</code> beginnt
  160. wird als Ressourcemethode angenommen.
  161. </para>
  162. <para>
  163. Um eine einzelne Ressource Methode zu bootstrappen, muß die <code>bootstrap()</code>
  164. Methode verwendet, und der Name der Ressource übergeben werden. Der Name ist der
  165. Name der Methode ohne den <code>_init</code> Präfix.
  166. </para>
  167. <para>
  168. Um mehrere Ressourcen Methoden zu bootstrappen, muß ein Array von Namen übergeben
  169. werden. Um alle Ressourcen Methoden zu bootstrappen, darf nichts übergeben werden.
  170. </para>
  171. <para>
  172. Nehmen wir die folgende Bootstrap Klasse an:
  173. </para>
  174. <programlisting language="php"><![CDATA[
  175. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  176. {
  177. protected function _initFoo()
  178. {
  179. // ...
  180. }
  181. protected function _initBar()
  182. {
  183. // ...
  184. }
  185. protected function _initBaz()
  186. {
  187. // ...
  188. }
  189. }
  190. ]]></programlisting>
  191. <para>
  192. Um nur die <code>_initFoo()</code> Methode zu bootstrappen, machen wir das folgende:
  193. </para>
  194. <programlisting language="php"><![CDATA[
  195. $bootstrap->bootstrap('foo');
  196. ]]></programlisting>
  197. <para>
  198. Um die Methoden <code>_initFoo()</code> und <code>_initBar()</code> zu bootstrappen,
  199. machen wir das folgende:
  200. </para>
  201. <programlisting language="php"><![CDATA[
  202. $bootstrap->bootstrap(array('foo', 'bar));
  203. ]]></programlisting>
  204. <para>
  205. Um alle Ressourcen Methoden zu bootstrappen, rufen wir <code>bootstrap()</code> ohne
  206. Argumente auf:
  207. </para>
  208. <programlisting language="php"><![CDATA[
  209. $bootstrap->bootstrap();
  210. ]]></programlisting>
  211. </sect3>
  212. <sect3 id="zend.application.theory-of-operation.bootstrap.resource-plugins">
  213. <title>Bootstraps die Ressourcen Plugins benutzen</title>
  214. <para>
  215. To make your bootstraps more re-usable, we have provided the
  216. ability to push your resources into resource plugin classes.
  217. This allows you to mix and match resources simply via
  218. configuration. We will cover <link
  219. linkend="zend.application.theory-of-operation.resources">how
  220. to create resources</link> later; in
  221. this section we will show you how to utilize them only.
  222. </para>
  223. <para>
  224. If your bootstrap should be capable of using resource plugins,
  225. you will need to implement an additional interface,
  226. <classname>Zend_Application_Bootstrap_ResourceBootstrapper</classname>.
  227. This interface defines an API for locating, registering, and
  228. loading resource plugins:
  229. </para>
  230. <programlisting language="php"><![CDATA[
  231. interface Zend_Application_Bootstrap_ResourceBootstrapper
  232. {
  233. public function registerPluginResource($resource, $options = null);
  234. public function unregisterPluginResource($resource);
  235. public function hasPluginResource($resource);
  236. public function getPluginResource($resource);
  237. public function getPluginResources();
  238. public function getPluginResourceNames();
  239. public function setPluginLoader(Zend_Loader_PluginLoader_Interface $loader);
  240. public function getPluginLoader();
  241. }
  242. ]]></programlisting>
  243. <para>
  244. Resource plugins basically provide the ability to create
  245. resource intializers that can be re-used between applications.
  246. This allows you to keep your actual bootstrap relatively clean,
  247. and to introduce new resources without needing to touch your
  248. bootstrap itself.
  249. </para>
  250. <para>
  251. <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname> (and
  252. <classname>Zend_Application_Bootstrap_Bootstrap</classname> by extension)
  253. implement this interface as well, allowing you to utilize
  254. resource plugins.
  255. </para>
  256. <para>
  257. To utilize resource plugins, you must specify them in the
  258. options passed to the application object and/or bootstrap. These
  259. options may come from a configuration file, or be passed in
  260. manually. Options will be of key/options pairs, with the key
  261. representing the resource name. The resource name will be the
  262. segment following the class prefix. For example, the resources
  263. shipped with Zend Framework have the class prefix
  264. "Zend_Application_Resource_"; anything following this would be
  265. the name of the resource. As an example,
  266. </para>
  267. <programlisting language="php"><![CDATA[
  268. $application = new Zend_Application(APPLICATION_ENV, array(
  269. 'resources' => array(
  270. 'FrontController' => array(
  271. 'controllerDirectory' => APPLICATION_PATH . '/controllers',
  272. ),
  273. ),
  274. ));
  275. ]]></programlisting>
  276. <para>
  277. This indicates that the "FrontController" resource should be
  278. used, with the options specified.
  279. </para>
  280. <para>
  281. If you begin writing your own resource plugins, or utilize
  282. third-party resource plugins, you will need to tell your
  283. bootstrap where to look for them. Internally, the bootstrap
  284. utilizes <classname>Zend_Loader_PluginLoader</classname>, so you will only
  285. need to indicate the common class prefix an path pairs.
  286. </para>
  287. <para>
  288. As an example, let's assume you have custom resource plugins in
  289. <code>APPLICATION_PATH/resources/</code> and that they share the
  290. common class prefix of <code>My_Resource</code>. You would then
  291. pass that information to the application object as follows:
  292. </para>
  293. <programlisting language="php"><![CDATA[
  294. $application = new Zend_Application(APPLICATION_ENV, array(
  295. 'pluginPaths' => array(
  296. 'My_Resource' => APPLICATION_PATH . '/resources/',
  297. ),
  298. 'resources' => array(
  299. 'FrontController' => array(
  300. 'controllerDirectory' => APPLICATION_PATH . '/controllers',
  301. ),
  302. ),
  303. ));
  304. ]]></programlisting>
  305. <para>
  306. You would now be able to use resources from that directory.
  307. </para>
  308. <para>
  309. Just like resource methods, you use the <code>bootstrap()</code>
  310. method to execute resource plugins. Just like with resource
  311. methods, you can specify either a single resource plugin,
  312. multiple plugins (via an array), or all plugins. Additionally,
  313. you can mix and match to execute resource methods as well.
  314. </para>
  315. <programlisting language="php"><![CDATA[
  316. // Execute one:
  317. $bootstrap->bootstrap('FrontController');
  318. // Execute several:
  319. $bootstrap->bootstrap(array('FrontController', 'Foo'));
  320. // Execute all resource methods and plugins:
  321. $bootstrap->bootstrap();
  322. ]]></programlisting>
  323. </sect3>
  324. <sect3 id="zend.application.theory-of-operation.bootstrap.registry">
  325. <title>Resource Registry</title>
  326. <para>
  327. Many, if not all, of your resource methods or plugins will
  328. initialize objects, and in many cases, these objects will be
  329. needed elsewhere in your application. How can you access them?
  330. </para>
  331. <para>
  332. <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname>
  333. provides a local registry for these objects. To store your
  334. objects in them, you simply return them from your resources.
  335. </para>
  336. <para>
  337. For maximum flexibility, this registry is referred to as a
  338. "container" internally; its only requirements are that it is an
  339. object. Resources are then registered as properties named after
  340. the resource name. By default, an instance of
  341. <classname>Zend_Registry</classname> is used, but you may also specify any
  342. other object you wish. The methods <code>setContainer()</code>
  343. and <code>getContainer()</code> may be used to manipulate the
  344. container itself. <code>getResource($resource)</code> can be
  345. used to fetch a given resource from the container, and
  346. <code>hasResource($resource)</code> to check if the resource has
  347. actually been registered.
  348. </para>
  349. <para>
  350. As an example, consider a basic view resource:
  351. </para>
  352. <programlisting language="php"><![CDATA[
  353. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  354. {
  355. protected function _initView()
  356. {
  357. $view = new Zend_View();
  358. // more initialization...
  359. return $view;
  360. }
  361. }
  362. ]]></programlisting>
  363. <para>
  364. You can then check for it and/or fetch it as follows:
  365. </para>
  366. <programlisting language="php"><![CDATA[
  367. // Using the has/getResource() pair:
  368. if ($bootstrap->hasResource('view')) {
  369. $view = $bootstrap->getResource('view');
  370. }
  371. // Via the container:
  372. $container = $bootstrap->getContainer();
  373. if (isset($container->view)) {
  374. $view = $container->view;
  375. }
  376. ]]></programlisting>
  377. <para>
  378. Please note that the registry/container is not global. This
  379. means that you need access to the bootstrap in order to fetch
  380. resources. <classname>Zend_Application_Bootstrap_Bootstrap</classname>
  381. provides some convenience for this: during its
  382. <code>run()</code> execution, it registers itself as the front
  383. controller parameter "bootstrap", which allows you to fetch it
  384. from the router, dispatcher, plugins, and action controllers.
  385. </para>
  386. <para>
  387. As an example, if you wanted access to the view resource from
  388. above within your action controller, you could do the following:
  389. </para>
  390. <programlisting language="php"><![CDATA[
  391. class FooController extends Zend_Controller_Action
  392. {
  393. public function init()
  394. {
  395. $bootstrap = $this->getInvokeArg('bootstrap');
  396. $view = $bootstrap->getResource('view');
  397. // ...
  398. }
  399. }
  400. ]]></programlisting>
  401. </sect3>
  402. <sect3 id="zend.application.theory-of-operation.bootstrap.dependency-tracking">
  403. <title>Dependency Tracking</title>
  404. <para>
  405. In addition to executing resource methods and plugins, it's
  406. necessary to ensure that these are executed once and once
  407. only; these are meant to bootstrap an application, and
  408. executing multiple times can lead to resource overhead.
  409. </para>
  410. <para>
  411. At the same time, some resources may depend on other
  412. resources being executed. To solve these two issues,
  413. <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname>
  414. provides a simple, effective mechanism for dependency
  415. tracking.
  416. </para>
  417. <para>
  418. As noted previously, all resources -- whether methods or plugins
  419. -- are bootstrapped by calling <code>bootstrap($resource)</code>,
  420. where <code>$resource</code> is the name of a resource, an array
  421. of resources, or, left empty, indicates all resources should be
  422. run.
  423. </para>
  424. <para>
  425. If a resource depends on another resource, it should call
  426. <code>bootstrap()</code> within its code to ensure that resource
  427. has been executed. Subsequent calls to it will then be ignored.
  428. </para>
  429. <para>
  430. In a resource method, such a call would look like this:
  431. </para>
  432. <programlisting language="php"><![CDATA[
  433. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  434. {
  435. protected function _initRequest()
  436. {
  437. // Ensure the front controller is initialized
  438. $this->bootstrap('FrontController');
  439. // Retrieve the front controller from the bootstrap registry
  440. $front = $this->getResource('FrontController');
  441. $request = new Zend_Controller_Request_Http();
  442. $request->setBaseUrl('/foo');
  443. $front->setRequest($request);
  444. // Ensure the request is stored in the bootstrap registry
  445. return $request;
  446. }
  447. }
  448. ]]></programlisting>
  449. </sect3>
  450. </sect2>
  451. <sect2 id="zend.application.theory-of-operation.resources">
  452. <title>Resource Plugins</title>
  453. <para>
  454. <link linkend="zend.application.theory-of-operation.bootstrap.resource-plugins">As noted
  455. previously</link>, a good way to create re-usable bootstrap resources and to offload
  456. much of your coding to discrete classes is to utilize resource
  457. plugins. While Zend Framework ships with a number of standard
  458. resource plugins, the intention is that developers should write
  459. their own to encapsulate their own intialization needs.
  460. </para>
  461. <para>
  462. Resources need only implement
  463. <classname>Zend_Application_Resource_Resource</classname>, or, more simply
  464. still, extend
  465. <classname>Zend_Application_Resource_ResourceAbstract</classname>. The basic
  466. interface is simply this:
  467. </para>
  468. <programlisting language="php"><![CDATA[
  469. interface Zend_Application_Resource_Resource
  470. {
  471. public function __construct($options = null);
  472. public function setBootstrap(
  473. Zend_Application_Bootstrap_Bootstrapper $bootstrap
  474. );
  475. public function getBootstrap();
  476. public function setOptions(array $options);
  477. public function getOptions();
  478. public function init();
  479. }
  480. ]]></programlisting>
  481. <para>
  482. The interface defines simply that a resource should accept options
  483. to the constructor, have mechanisms for setting and retrieving
  484. options, have mechanisms for setting and retrieving the bootstrap
  485. object, and an initialization method.
  486. </para>
  487. <para>
  488. As an example, let's assume you have a common view intialization you
  489. use in your applications. You have a common doctype, CSS and
  490. JavaScript, and you want to be able to pass in a base document title
  491. via configuration. Such a resource might look like this:
  492. </para>
  493. <programlisting language="php"><![CDATA[
  494. class My_Resource_View extends Zend_Application_Resource_ResourceAbstract
  495. {
  496. protected $_view;
  497. public function init()
  498. {
  499. // Return view so bootstrap will store it in the registry
  500. return $this->getView();
  501. }
  502. public function getView()
  503. {
  504. if (null === $this->_view) {
  505. $options = $this->getOptions();
  506. $title = '';
  507. if (array_key_exists('title', $options)) {
  508. $title = $options['title'];
  509. unset($options['title']);
  510. }
  511. $view = new Zend_View($options);
  512. $view->doctype('XHTML1_STRICT');
  513. $view->headTitle($title);
  514. $view->headLink()->appendStylesheet('/css/site.css');
  515. $view->headScript()->appendfile('/js/analytics.js');
  516. $viewRenderer =
  517. Zend_Controller_Action_HelperBroker::getStaticHelper(
  518. 'ViewRenderer',
  519. );
  520. $viewRenderer->setView($view);
  521. $this->_view = $view;
  522. }
  523. return $this->_view;
  524. }
  525. }
  526. ]]></programlisting>
  527. <para>
  528. As long as you register the prefix path for this resource plugin,
  529. you can then use it in your application. Even better, because it
  530. uses the plugin loader, you are effectively overriding the shipped
  531. "View" resource plugin, ensuring that your own is used instead.
  532. </para>
  533. </sect2>
  534. </sect1>