Zend_Application-TheoryOfOperation.xml 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- EN-Revision: 15734 -->
  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 <emphasis>_init</emphasis> beginnt
  160. wird als Ressourcemethode angenommen.
  161. </para>
  162. <para>
  163. Um eine einzelne Ressource Methode zu bootstrappen, muß die
  164. <methodname>bootstrap()</methodname> Methode verwendet, und der Name der Ressource
  165. übergeben werden. Der Name ist der Name der Methode ohne den
  166. <emphasis>_init</emphasis> Präfix.
  167. </para>
  168. <para>
  169. Um mehrere Ressourcen Methoden zu bootstrappen, muß ein Array von Namen übergeben
  170. werden. Um alle Ressourcen Methoden zu bootstrappen, darf nichts übergeben werden.
  171. </para>
  172. <para>
  173. Nehmen wir die folgende Bootstrap Klasse an:
  174. </para>
  175. <programlisting language="php"><![CDATA[
  176. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  177. {
  178. protected function _initFoo()
  179. {
  180. // ...
  181. }
  182. protected function _initBar()
  183. {
  184. // ...
  185. }
  186. protected function _initBaz()
  187. {
  188. // ...
  189. }
  190. }
  191. ]]></programlisting>
  192. <para>
  193. Um nur die <methodname>_initFoo()</methodname> Methode zu bootstrappen, machen wir
  194. das folgende:
  195. </para>
  196. <programlisting language="php"><![CDATA[
  197. $bootstrap->bootstrap('foo');
  198. ]]></programlisting>
  199. <para>
  200. Um die Methoden <methodname>_initFoo()</methodname> und
  201. <methodname>_initBar()</methodname> zu bootstrappen, machen wir das folgende:
  202. </para>
  203. <programlisting language="php"><![CDATA[
  204. $bootstrap->bootstrap(array('foo', 'bar));
  205. ]]></programlisting>
  206. <para>
  207. Um alle Ressourcen Methoden zu bootstrappen, rufen wir
  208. <methodname>bootstrap()</methodname> ohne Argumente auf:
  209. </para>
  210. <programlisting language="php"><![CDATA[
  211. $bootstrap->bootstrap();
  212. ]]></programlisting>
  213. </sect3>
  214. <sect3 id="zend.application.theory-of-operation.bootstrap.resource-plugins">
  215. <title>Bootstraps die Ressourcen Plugins benutzen</title>
  216. <para>
  217. To make your bootstraps more re-usable, we have provided the
  218. ability to push your resources into resource plugin classes.
  219. This allows you to mix and match resources simply via
  220. configuration. We will cover <link
  221. linkend="zend.application.theory-of-operation.resources">how
  222. to create resources</link> later; in
  223. this section we will show you how to utilize them only.
  224. </para>
  225. <para>
  226. If your bootstrap should be capable of using resource plugins,
  227. you will need to implement an additional interface,
  228. <classname>Zend_Application_Bootstrap_ResourceBootstrapper</classname>.
  229. This interface defines an API for locating, registering, and
  230. loading resource plugins:
  231. </para>
  232. <programlisting language="php"><![CDATA[
  233. interface Zend_Application_Bootstrap_ResourceBootstrapper
  234. {
  235. public function registerPluginResource($resource, $options = null);
  236. public function unregisterPluginResource($resource);
  237. public function hasPluginResource($resource);
  238. public function getPluginResource($resource);
  239. public function getPluginResources();
  240. public function getPluginResourceNames();
  241. public function setPluginLoader(Zend_Loader_PluginLoader_Interface $loader);
  242. public function getPluginLoader();
  243. }
  244. ]]></programlisting>
  245. <para>
  246. Resource plugins basically provide the ability to create
  247. resource intializers that can be re-used between applications.
  248. This allows you to keep your actual bootstrap relatively clean,
  249. and to introduce new resources without needing to touch your
  250. bootstrap itself.
  251. </para>
  252. <para>
  253. <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname> (and
  254. <classname>Zend_Application_Bootstrap_Bootstrap</classname> by extension)
  255. implement this interface as well, allowing you to utilize
  256. resource plugins.
  257. </para>
  258. <para>
  259. To utilize resource plugins, you must specify them in the
  260. options passed to the application object and/or bootstrap. These
  261. options may come from a configuration file, or be passed in
  262. manually. Options will be of key/options pairs, with the key
  263. representing the resource name. The resource name will be the
  264. segment following the class prefix. For example, the resources
  265. shipped with Zend Framework have the class prefix
  266. "Zend_Application_Resource_"; anything following this would be
  267. the name of the resource. As an example,
  268. </para>
  269. <programlisting language="php"><![CDATA[
  270. $application = new Zend_Application(APPLICATION_ENV, array(
  271. 'resources' => array(
  272. 'FrontController' => array(
  273. 'controllerDirectory' => APPLICATION_PATH . '/controllers',
  274. ),
  275. ),
  276. ));
  277. ]]></programlisting>
  278. <para>
  279. This indicates that the "FrontController" resource should be
  280. used, with the options specified.
  281. </para>
  282. <para>
  283. If you begin writing your own resource plugins, or utilize
  284. third-party resource plugins, you will need to tell your
  285. bootstrap where to look for them. Internally, the bootstrap
  286. utilizes <classname>Zend_Loader_PluginLoader</classname>, so you will only
  287. need to indicate the common class prefix an path pairs.
  288. </para>
  289. <para>
  290. As an example, let's assume you have custom resource plugins in
  291. <filename>APPLICATION_PATH/resources/</filename> and that they share the
  292. common class prefix of <classname>My_Resource</classname>. You would then
  293. pass that information to the application object as follows:
  294. </para>
  295. <programlisting language="php"><![CDATA[
  296. $application = new Zend_Application(APPLICATION_ENV, array(
  297. 'pluginPaths' => array(
  298. 'My_Resource' => APPLICATION_PATH . '/resources/',
  299. ),
  300. 'resources' => array(
  301. 'FrontController' => array(
  302. 'controllerDirectory' => APPLICATION_PATH . '/controllers',
  303. ),
  304. ),
  305. ));
  306. ]]></programlisting>
  307. <para>
  308. You would now be able to use resources from that directory.
  309. </para>
  310. <para>
  311. Just like resource methods, you use the <methodname>bootstrap()</methodname>
  312. method to execute resource plugins. Just like with resource
  313. methods, you can specify either a single resource plugin,
  314. multiple plugins (via an array), or all plugins. Additionally,
  315. you can mix and match to execute resource methods as well.
  316. </para>
  317. <programlisting language="php"><![CDATA[
  318. // Execute one:
  319. $bootstrap->bootstrap('FrontController');
  320. // Execute several:
  321. $bootstrap->bootstrap(array('FrontController', 'Foo'));
  322. // Execute all resource methods and plugins:
  323. $bootstrap->bootstrap();
  324. ]]></programlisting>
  325. </sect3>
  326. <sect3 id="zend.application.theory-of-operation.bootstrap.registry">
  327. <title>Resource Registry</title>
  328. <para>
  329. Many, if not all, of your resource methods or plugins will
  330. initialize objects, and in many cases, these objects will be
  331. needed elsewhere in your application. How can you access them?
  332. </para>
  333. <para>
  334. <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname>
  335. provides a local registry for these objects. To store your
  336. objects in them, you simply return them from your resources.
  337. </para>
  338. <para>
  339. For maximum flexibility, this registry is referred to as a
  340. "container" internally; its only requirements are that it is an
  341. object. Resources are then registered as properties named after
  342. the resource name. By default, an instance of
  343. <classname>Zend_Registry</classname> is used, but you may also specify any
  344. other object you wish. The methods <methodname>setContainer()</methodname>
  345. and <methodname>getContainer()</methodname> may be used to manipulate the
  346. container itself. <methodname>getResource($resource)</methodname> can be
  347. used to fetch a given resource from the container, and
  348. <methodname>hasResource($resource)</methodname> to check if the resource has
  349. actually been registered.
  350. </para>
  351. <para>
  352. As an example, consider a basic view resource:
  353. </para>
  354. <programlisting language="php"><![CDATA[
  355. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  356. {
  357. protected function _initView()
  358. {
  359. $view = new Zend_View();
  360. // more initialization...
  361. return $view;
  362. }
  363. }
  364. ]]></programlisting>
  365. <para>
  366. You can then check for it and/or fetch it as follows:
  367. </para>
  368. <programlisting language="php"><![CDATA[
  369. // Using the has/getResource() pair:
  370. if ($bootstrap->hasResource('view')) {
  371. $view = $bootstrap->getResource('view');
  372. }
  373. // Via the container:
  374. $container = $bootstrap->getContainer();
  375. if (isset($container->view)) {
  376. $view = $container->view;
  377. }
  378. ]]></programlisting>
  379. <para>
  380. Please note that the registry/container is not global. This
  381. means that you need access to the bootstrap in order to fetch
  382. resources. <classname>Zend_Application_Bootstrap_Bootstrap</classname>
  383. provides some convenience for this: during its
  384. <methodname>run()</methodname> execution, it registers itself as the front
  385. controller parameter "bootstrap", which allows you to fetch it
  386. from the router, dispatcher, plugins, and action controllers.
  387. </para>
  388. <para>
  389. As an example, if you wanted access to the view resource from
  390. above within your action controller, you could do the following:
  391. </para>
  392. <programlisting language="php"><![CDATA[
  393. class FooController extends Zend_Controller_Action
  394. {
  395. public function init()
  396. {
  397. $bootstrap = $this->getInvokeArg('bootstrap');
  398. $view = $bootstrap->getResource('view');
  399. // ...
  400. }
  401. }
  402. ]]></programlisting>
  403. </sect3>
  404. <sect3 id="zend.application.theory-of-operation.bootstrap.dependency-tracking">
  405. <title>Dependency Tracking</title>
  406. <para>
  407. In addition to executing resource methods and plugins, it's
  408. necessary to ensure that these are executed once and once
  409. only; these are meant to bootstrap an application, and
  410. executing multiple times can lead to resource overhead.
  411. </para>
  412. <para>
  413. At the same time, some resources may depend on other
  414. resources being executed. To solve these two issues,
  415. <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname>
  416. provides a simple, effective mechanism for dependency
  417. tracking.
  418. </para>
  419. <para>
  420. As noted previously, all resources -- whether methods or plugins
  421. -- are bootstrapped by calling <methodname>bootstrap($resource)</methodname>,
  422. where <varname>$resource</varname> is the name of a resource, an array
  423. of resources, or, left empty, indicates all resources should be
  424. run.
  425. </para>
  426. <para>
  427. If a resource depends on another resource, it should call
  428. <methodname>bootstrap()</methodname> within its code to ensure that resource
  429. has been executed. Subsequent calls to it will then be ignored.
  430. </para>
  431. <para>
  432. In a resource method, such a call would look like this:
  433. </para>
  434. <programlisting language="php"><![CDATA[
  435. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  436. {
  437. protected function _initRequest()
  438. {
  439. // Ensure the front controller is initialized
  440. $this->bootstrap('FrontController');
  441. // Retrieve the front controller from the bootstrap registry
  442. $front = $this->getResource('FrontController');
  443. $request = new Zend_Controller_Request_Http();
  444. $request->setBaseUrl('/foo');
  445. $front->setRequest($request);
  446. // Ensure the request is stored in the bootstrap registry
  447. return $request;
  448. }
  449. }
  450. ]]></programlisting>
  451. </sect3>
  452. </sect2>
  453. <sect2 id="zend.application.theory-of-operation.resources">
  454. <title>Resource Plugins</title>
  455. <para>
  456. <link linkend="zend.application.theory-of-operation.bootstrap.resource-plugins">As noted
  457. previously</link>, a good way to create re-usable bootstrap resources and to offload
  458. much of your coding to discrete classes is to utilize resource
  459. plugins. While Zend Framework ships with a number of standard
  460. resource plugins, the intention is that developers should write
  461. their own to encapsulate their own intialization needs.
  462. </para>
  463. <para>
  464. Resources need only implement
  465. <classname>Zend_Application_Resource_Resource</classname>, or, more simply
  466. still, extend
  467. <classname>Zend_Application_Resource_ResourceAbstract</classname>. The basic
  468. interface is simply this:
  469. </para>
  470. <programlisting language="php"><![CDATA[
  471. interface Zend_Application_Resource_Resource
  472. {
  473. public function __construct($options = null);
  474. public function setBootstrap(
  475. Zend_Application_Bootstrap_Bootstrapper $bootstrap
  476. );
  477. public function getBootstrap();
  478. public function setOptions(array $options);
  479. public function getOptions();
  480. public function init();
  481. }
  482. ]]></programlisting>
  483. <para>
  484. The interface defines simply that a resource should accept options
  485. to the constructor, have mechanisms for setting and retrieving
  486. options, have mechanisms for setting and retrieving the bootstrap
  487. object, and an initialization method.
  488. </para>
  489. <para>
  490. As an example, let's assume you have a common view intialization you
  491. use in your applications. You have a common doctype, CSS and
  492. JavaScript, and you want to be able to pass in a base document title
  493. via configuration. Such a resource might look like this:
  494. </para>
  495. <programlisting language="php"><![CDATA[
  496. class My_Resource_View extends Zend_Application_Resource_ResourceAbstract
  497. {
  498. protected $_view;
  499. public function init()
  500. {
  501. // Return view so bootstrap will store it in the registry
  502. return $this->getView();
  503. }
  504. public function getView()
  505. {
  506. if (null === $this->_view) {
  507. $options = $this->getOptions();
  508. $title = '';
  509. if (array_key_exists('title', $options)) {
  510. $title = $options['title'];
  511. unset($options['title']);
  512. }
  513. $view = new Zend_View($options);
  514. $view->doctype('XHTML1_STRICT');
  515. $view->headTitle($title);
  516. $view->headLink()->appendStylesheet('/css/site.css');
  517. $view->headScript()->appendfile('/js/analytics.js');
  518. $viewRenderer =
  519. Zend_Controller_Action_HelperBroker::getStaticHelper(
  520. 'ViewRenderer',
  521. );
  522. $viewRenderer->setView($view);
  523. $this->_view = $view;
  524. }
  525. return $this->_view;
  526. }
  527. }
  528. ]]></programlisting>
  529. <para>
  530. As long as you register the prefix path for this resource plugin,
  531. you can then use it in your application. Even better, because it
  532. uses the plugin loader, you are effectively overriding the shipped
  533. "View" resource plugin, ensuring that your own is used instead.
  534. </para>
  535. </sect2>
  536. </sect1>