| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 15823 -->
- <!-- Reviewed: no -->
- <sect1 id="zend.application.theory-of-operation">
- <title>Theorie der Funktionsweise</title>
- <para>
- Um eine <acronym>MVC</acronym> Anwendung zu konfigurieren und bereit zur Auslieferung
- zu bekommen wird ein immer größerer Anteil an Code benötigt sobald mehr Features verfügbar
- sind: Setzen der Datenbank, Konfiguration der View und View Helfer, Konfiguration der
- Layouts, Registrierung der Plugins, Registrierung der Aktion Helfer, und andere.
- </para>
- <para>
- Zusätzlich will man oft den gleichen Code wiederverwenden um Tests zu bootstrappen, einen
- Cronjob, oder ein Service Skript zu haben. Wärend es sehr einfach ist sein Bootstrap Skript
- einzubauen, gibt es oft Initialisierungen die abhängig sind von der Umgebung - man könnte
- kein <acronym>MVC</acronym> für einen Cronjob benötigen, oder nur den DB Layer für ein
- Service Skript.
- </para>
- <para>
- <classname>Zend_Application</classname> zielt darauf ab das alles einfacher zu machen und
- bietet Wiederwervendbarkeit durch die Kapselung vom Bootstrapping in <acronym>OOP</acronym>
- Paradigmen.
- </para>
- <para>
- <classname>Zend_Application</classname> ist in drei Bereiche geteilt:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <classname>Zend_Application</classname>: Lädt die <acronym>PHP</acronym> Umgebung,
- inklusive Inklude-Pfade und Autoloading, und instanziiert die benötigte Bootstrap
- Klasse.
- </para>
- </listitem>
- <listitem>
- <para>
- <classname>Zend_Application_Bootstrap</classname>: Bietet Interfaces für Bootstrap
- Klassen. <classname>Zend_Application_Bootstrap_Bootstrap</classname> bietet übliche
- Funktionalitäten für die meisten Notwendigkeiten des Bootstrappings, inklusive
- Angorithmen um Abhängigkeiten zu prüfen und die Möglichkeit Bootstrap Ressourcen bei
- Bedarf zu laden.
- </para>
- </listitem>
- <listitem>
- <para>
- <classname>Zend_Application_Resource</classname> bietet ein Interface für Standard
- Bootstrap Ressourcen die bei Bedarf von einer Bootstrap Instanz geladen werden
- können, sowie verschiedene standardmäßige Ressource Implementationen.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- Entwickler erstellen eine Bootstrap Klasse für Ihre Anwendung und erweitern
- <classname>Zend_Application_Bootstrap_Bootstrap</classname> oder implementieren (mindestens)
- <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname>. Der Einstiegspunkt
- (z.B. <filename>public/index.php</filename>) lädt <classname>Zend_Application</classname>
- und initialisiert Sie, indem folgendes übergeben wird:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- Die aktuelle Umgebung
- </para>
- </listitem>
- <listitem>
- <para>
- Optionen für das Bootstrapping
- </para>
- </listitem>
- </itemizedlist>
- <para>
- Die Bootstrap Optionen enthalten den Pfad zur Datei die die Bootstrap Klasse enthält und
- optional:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- Jeden include_path der extra zu setzen ist
- </para>
- </listitem>
- <listitem>
- <para>
- Jeden Autoloader Namespace der zusätzlich zu registrieren ist
- </para>
- </listitem>
- <listitem>
- <para>
- Jede <filename>php.ini</filename> Einstellung die zu initialisieren ist
- </para>
- </listitem>
- <listitem>
- <para>
- Den Klassennamen für die Bootstrap Klasse (wenn diese nicht "Bootstrap" ist)
- </para>
- </listitem>
- <listitem>
- <para>
- Ressourcen Präfix zu Pfad Paare die zu verwenden sind
- </para>
- </listitem>
- <listitem>
- <para>
- Jede Ressource die zu verwenden ist (durch Name der Klasse oder Kurzname)
- </para>
- </listitem>
- <listitem>
- <para>
- Zusätzliche Pfade zu einer Konfigurationsdatei die zu laden ist
- </para>
- </listitem>
- <listitem>
- <para>
- Zusätzliche Konfigurations Optionen
- </para>
- </listitem>
- </itemizedlist>
- <para>
- Optionen können, ein Array, ein <classname>Zend_Config</classname> Objekt, oder der Pfad zu
- einer Konfigurationsdatei sein.
- </para>
- <sect2 id="zend.application.theory-of-operation.bootstrap">
- <title>Bootstrapping</title>
- <para>
- <classname>Zend_Application</classname>'s zweites Feld der Arbeit ist die Ausführung des
- Bootstraps der Anwendung. Bootstraps müssen mindestens
- <classname>Zend_Application_Bootstrap_Bootstrapper</classname> implementieren, welches
- die folgende <acronym>API</acronym> definiert:
- </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>
- Diese <acronym>API</acronym> erlaubt es dem Bootstrap die Umgebung und die
- Konfiguration vom Objekt der Anwendung zu akzeptieren, die Ressourcen die für das
- Bootstrapping verantwortlich sind zu melden, und dann das Bootstrappen ausführen und
- die Anwendung zu starten.
- </para>
- <para>
- Man kann dieses Interface selbst implementieren,
- <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname> erweitern, oder
- <classname>Zend_Application_Bootstrap_Bootstrap</classname> verwenden.
- </para>
- <para>
- Neben dieser Funktionalität gibt es eine Anzahl anderer Gebiete von Interesse mit denen
- man vertraut sein sollte.
- </para>
- <sect3 id="zend.application.theory-of-operation.bootstrap.resource-methods">
- <title>Methoden für Ressourcen</title>
- <para>
- Die Implementation von
- <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname> bietet eine
- einfache Konvention für die Definition von Methoden für Ressourcen Klassen. Jede
- geschützte Methode (protected), deren Name mit <emphasis>_init</emphasis> beginnt
- wird als Ressourcemethode angenommen.
- </para>
- <para>
- Um eine einzelne Ressource Methode zu bootstrappen, muß die
- <methodname>bootstrap()</methodname> Methode verwendet, und der Name der Ressource
- übergeben werden. Der Name ist der Name der Methode ohne den
- <emphasis>_init</emphasis> Präfix.
- </para>
- <para>
- Um mehrere Ressourcen Methoden zu bootstrappen, muß ein Array von Namen übergeben
- werden. Um alle Ressourcen Methoden zu bootstrappen, darf nichts übergeben werden.
- </para>
- <para>
- Nehmen wir die folgende Bootstrap Klasse an:
- </para>
- <programlisting language="php"><![CDATA[
- class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
- {
- protected function _initFoo()
- {
- // ...
- }
- protected function _initBar()
- {
- // ...
- }
- protected function _initBaz()
- {
- // ...
- }
- }
- ]]></programlisting>
- <para>
- Um nur die <methodname>_initFoo()</methodname> Methode zu bootstrappen, machen wir
- das folgende:
- </para>
- <programlisting language="php"><![CDATA[
- $bootstrap->bootstrap('foo');
- ]]></programlisting>
- <para>
- Um die Methoden <methodname>_initFoo()</methodname> und
- <methodname>_initBar()</methodname> zu bootstrappen, machen wir das folgende:
- </para>
- <programlisting language="php"><![CDATA[
- $bootstrap->bootstrap(array('foo', 'bar));
- ]]></programlisting>
- <para>
- Um alle Ressourcen Methoden zu bootstrappen, rufen wir
- <methodname>bootstrap()</methodname> ohne Argumente auf:
- </para>
- <programlisting language="php"><![CDATA[
- $bootstrap->bootstrap();
- ]]></programlisting>
- </sect3>
- <sect3 id="zend.application.theory-of-operation.bootstrap.resource-plugins">
- <title>Bootstraps die Ressourcen Plugins benutzen</title>
- <para>
- Um Bootstraps wiederverwendbarer zu machen wurde die Fähigkeit zur Verfügung
- gestellt Ressourcen in Ressource Plugin Klassen zu geben. Das erlaubt es Ressourcen
- einfach über die Konfiguration zu mischen und zu sehen ob Sie passen. Wir behandeln
- später <link linkend="zend.application.theory-of-operation.resources">wie
- Ressourcen erstellt werden</link>; in diesem Abschnitt zeigen wir nur wie Sie
- angepasst werden können.
- </para>
- <para>
- Wenn die Bootstrap dazu in der Lage sein soll Ressource Plugins zu verwenden muß
- man ein zusätzliches Interface implementieren,
- <classname>Zend_Application_Bootstrap_ResourceBootstrapper</classname>. Dieses
- Interface definiert eine <acronym>API</acronym> für das Erkennen, Registrieren und
- Laden von Ressource Plugins:
- </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>
- Ressource Plugins bieten grundsätzlich die Fähigkeit Ressource Initialisierer zu
- Erstellen die zwischen Anwendungen wiederverwendet werden können. Das erlaubt es
- die aktuelle Bootstrap relativ klein zu halten, und neue Ressourcen einzuführen
- ohne Sie in der Bootstrap selbst anzugreifen.
- </para>
- <para>
- <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname> (und bei
- Erweiterung <classname>Zend_Application_Bootstrap_Bootstrap</classname>)
- implementiert dieses Interface genauso, und erlaubt es Ressource Plugins zu
- verwenden.
- </para>
- <para>
- Um Ressource Plugins zu verwenden müssen diese in den Optionen spezifiziert
- werden, die dem Anwendungs Objekt und-oder der Bootstrap übergeben werden. Diese
- Optionen können von einer Konfigurationsdatei kommen, oder manuell übergeben
- werden. Optionen sind Paare von Schlüssel zu Optionspaaren, wobei der Schlüssel
- den Namen der Ressource repräsentiert. Der Ressourcename ist das Segment das
- dem Klassenpräfix folgt. Die Ressourcen, die zum Beispiel mit Zend Framework
- ausgeliefert werden, haben den Klassenpräfix
- "<classname>Zend_Application_Resource_</classname>"; alles was folgt würde der
- Name der Ressource sein. Als Beispiel:
- </para>
- <programlisting language="php"><![CDATA[
- $application = new Zend_Application(APPLICATION_ENV, array(
- 'resources' => array(
- 'FrontController' => array(
- 'controllerDirectory' => APPLICATION_PATH . '/controllers',
- ),
- ),
- ));
- ]]></programlisting>
- <para>
- Das zeigt das die "FrontController" verwendet werden sollte, mit den spezifizierten
- Optionen.
- </para>
- <para>
- Wenn man beginnt eigene Ressource Plugins zu schreiben, oder Ressource Plugins von
- dritten anzupassen, muß man der eigenen Bootstrap mitteilen wo nach Ihnen zu suchen
- ist. Intern verwendet die Bootstrap <classname>Zend_Loader_PluginLoader</classname>
- so dass man nur die üblichen Klassenpräfix und Pfadpaare angeben muß.
- </para>
- <para>
- Als Beispiel nehmen wir an das wir eigene Ressource Plugins in
- <filename>APPLICATION_PATH/resources/</filename> haben, und das sie den gemeinsamen
- Klassenpräfix <classname>My_Resource</classname> teilen. Man würde diese
- Information de Anwendungsobjekt wie folgt übergeben:
- </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>
- Man ist jetzt in der Lage Ressource von diesem Verzeichnis zu verwenden.
- </para>
- <para>
- Wie Ressource Methoden kann die <methodname>bootstrap()</methodname> Methode
- verwendet werden um Ressource Plugins zu verwenden. Wie bei Ressource Methoden
- kann man entweder einzelne Ressource Plugins spezifizieren, mehrere Plugins
- (über ein Array), oder alle Plugins. Zusätzlich kann man mischen und entsprechende
- Ressource Methoden genauso ausführen.
- </para>
- <programlisting language="php"><![CDATA[
- // Eine ausführen:
- $bootstrap->bootstrap('FrontController');
- // Mehrere ausführen:
- $bootstrap->bootstrap(array('FrontController', 'Foo'));
- // Alle Ressource Methoden und Plugins ausführen:
- $bootstrap->bootstrap();
- ]]></programlisting>
- </sect3>
- <sect3 id="zend.application.theory-of-operation.bootstrap.registry">
- <title>Ressource Registry</title>
- <para>
- Viele, wenn nicht sogar alle, der eigenen Ressource Methoden oder Plugins
- initialisieren Objekte, und in vielen Fällen werden diese Objekte an anderen
- Orten der Anwendung benötigt. Wie man man auf Sie zugreifen?
- </para>
- <para>
- <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname>
- bietet eine locale Registry für diese Objekte. Um eigene Objekte in Ihr zu
- Speichern müssen diese einfach von den eigenen Ressourcen zurückgegeben werden.
- </para>
- <para>
- Für maximale Flexibilität wird diese Registry intern als "Container" bezeichnet;
- die einzige Voraussetzung ist das es ein Objekt ist. Ressourcen werden dann als
- Eigenschaften registriert die nach dem Namen der Ressource benannt sind.
- Standardmäßig wird eine Instanz von <classname>Zend_Registry</classname> verwendet,
- man kann aber jedes andere Objekt spezifizieren wenn man das will. Die Methoden
- <methodname>setContainer()</methodname> und <methodname>getContainer()</methodname>
- können verwendet werden um den Container selber zu manipulieren.
- <methodname>getResource($resource)</methodname> kann verwendet werden um eine
- angegebene Ressource vom Container zu holen, und
- <methodname>hasResource($resource)</methodname> um zu prüfen ob die Ressource
- aktuell schon registriert wurde.
- </para>
- <para>
- Als Beispiel nehmen wir eine grundsätzliche View Ressource an:
- </para>
- <programlisting language="php"><![CDATA[
- class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
- {
- protected function _initView()
- {
- $view = new Zend_View();
- // weitere Initialisierungen...
- return $view;
- }
- }
- ]]></programlisting>
- <para>
- Man kann Sie prüfen und-oder Sie wie folgt holen:
- </para>
- <programlisting language="php"><![CDATA[
- // Verwendung der has- und getResource() Paare:
- if ($bootstrap->hasResource('view')) {
- $view = $bootstrap->getResource('view');
- }
- // Über den Container:
- $container = $bootstrap->getContainer();
- if (isset($container->view)) {
- $view = $container->view;
- }
- ]]></programlisting>
- <para>
- Es ist zu beachten das die Registry und auch der Container nicht global sind. Das
- bedeutet das man auf die Bootstrap zugreifen muß um Ressourcen zu holen.
- <classname>Zend_Application_Bootstrap_Bootstrap</classname> bietet einige
- Bequemlichkeiten hierfür: wärend der Ausführung von
- <methodname>run()</methodname>, registriert Sie sich als Front Controller Parameter
- "bootstrap", was es erlaubt Sie von Routern, Dispatchern, Plugins, und
- Action Controllern zu holen.
- </para>
- <para>
- Wenn man, als Beispiel, auf die View Ressource von oben im eigenen Action
- Controller zugreifen will, kann man das wie folgt tun:
- </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>Erkennen von Abhängigkeiten</title>
- <para>
- Zusätzlich zur Ausführung von Ressource Methoden und Plugins, ist es notwendig
- sicherzustellen das diese einmal und wirklich nur einmal ausgeführt werden; Sie
- sollen eine Anwendung bootstrappen, und die mehrfache Ausführung von Ihnen kann
- zu einem Overhead von Ressourcen führen.
- </para>
- <para>
- Zur gleichen Zeit können Ressourcen von anderen ausgeführten Ressourcen abhängen.
- Um diese zwei Fälle zu lösen bietet
- <classname>Zend_Application_Bootstrap_BootstrapAbstract</classname> einen einfachen
- und effektiven Mechanismus für die Erkennung von Abhängigkeiten.
- </para>
- <para>
- Wie vorher erwähnt werden alle Ressourcen -- ob Methoden oder Plugins -- durch den
- Aufruf von <methodname>bootstrap($resource)</methodname> gebootstrappt, wobei
- <varname>$resource</varname> der Name einer Ressource ist, ein Array von Ressourcen
- oder leer gelassen wird, was zeigt das alle Ressourcen ausgeführt werden sollen.
- </para>
- <para>
- Wenn eine Ressource von anderen Ressourcen abhängig ist, sollte Sie in Ihrem Code
- <methodname>bootstrap()</methodname> aufrufen um sicherzustellen das die Ressource
- ausgeführt wurde. Weitere Aufrufe von Ihr werden dann ignoriert.
- </para>
- <para>
- In einer Ressource Methode würde so ein Aufruf wie folgt aussehen:
- </para>
- <programlisting language="php"><![CDATA[
- class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
- {
- protected function _initRequest()
- {
- // Sicherstellen der der Front Controlle initialisiert wird
- $this->bootstrap('FrontController');
- // Den Front Controller von der Bootstrap Registry erhalten
- $front = $this->getResource('FrontController');
- $request = new Zend_Controller_Request_Http();
- $request->setBaseUrl('/foo');
- $front->setRequest($request);
- // Sicherstellen das die Anfrage in der Bootstrap Registry gespeichert ist
- return $request;
- }
- }
- ]]></programlisting>
- </sect3>
- </sect2>
- <sect2 id="zend.application.theory-of-operation.resources">
- <title>Ressource Plugins</title>
- <para>
- <link linkend="zend.application.theory-of-operation.bootstrap.resource-plugins">Wie
- vorher erwähnt</link> ist die Verwendung von Ressource Plugins ein guter Weg um
- wiederverwendbare Bootstrap Ressourcen zu erstellen und um so viel wie möglich vom
- eigenen Code in diskrete Klassen auszulagern. Wärend Zend Framework mit einer Anzahl
- von standardmäßigen Ressource Plugins geliefert wird, besteht das Ziel darin das der
- Entwickler eigene schreiben sollte um seine eigenen Notwendigkeiten der
- Initialisierung zu kapseln.
- </para>
- <para>
- Ressourcen müssen nur <classname>Zend_Application_Resource_Resource</classname>
- implementieren, oder einfach
- <classname>Zend_Application_Resource_ResourceAbstract</classname> erweitern. Das
- grundsätzliche Interface ist folgendes:
- </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>
- Das Interface definiert einfach das eine Ressouce Optionen im Konstruktor akzeptieren
- sollte, Mechanismen für das Setzen und Empfangen von Optionen, Mechanismen für das
- Setzen und Empfangen des Bootstrap Objekts, und eine Initialisierungs-Methode hat.
- </para>
- <para>
- Als Beispiel nehmen wir an das wir eine normale View Initialisierung haben die in der
- eigenen Anwendung verwendet wird. Man hat normale Doctype, <acronym>CSS</acronym> und
- Javascript, und will in der Lage sein diese in einem basis Dokumententitel über die
- Konfiguration zu übergeben. So eine Ressource könnte wie folgt aussehen:
- </para>
- <programlisting language="php"><![CDATA[
- class My_Resource_View extends Zend_Application_Resource_ResourceAbstract
- {
- protected $_view;
- public function init()
- {
- // Die View zurückgeben damit die Bootstrap Sie in der Registry speichert
- 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>
- Solange man den Präfix Pfad für dieses Ressource Plugin registriert, kann es in der
- eigenen Anwendung verwendet werden. Besser, weil der Plugin Loader verwendet wird, ist
- es die gelieferten "View" Ressource Plugin zu überschreiben, und sicherzustellen das
- man stattdessen die eigene verwendet.
- </para>
- </sect2>
- </sect1>
|