| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 24249 -->
- <!-- Reviewed: no -->
- <sect1 id="zend.loader.pluginloader">
- <title>Plugins laden</title>
- <para>
- Eine Anzahl von Zend Framework Komponenten ist steckbar, und erlaubt es Funktionen dynamisch
- zu laden durch die Angabe eines Klassenpräfixes und einem Pfad zu den Klassendaten die nicht
- notwendigerweise im <property>include_path</property> sind, oder nicht notwendigerweise den
- traditionellen Namenskonventionen folgen. <classname>Zend_Loader_PluginLoader</classname>
- bietet übliche Funktionalitäten für diesen Prozess.
- </para>
- <para>
- Die grundsätzliche Verwendung vom <classname>PluginLoader</classname> folgt den
- Namenskonventionen vom Zend Framework mit einer Klasse pro Datei, der Verwendung von
- Unterstrichen als Verzeichnistrenner bei der Auflösung von Pfaden. Es erlaubt die Übergabe
- eines optionalen Klasenpräfixes der vorangestellt wird, wenn eine bestimmte Pluginklasse
- geladen wird. Zusätzlich können Pfade in LIFO Reihenfolge durchsucht werden. Die LIFO Suche
- und der Klassen Präfix erlaubt es für die Plugins Namensräumen zu definieren, und auf diese
- Weise Plugins zu überladen die vorher registriert wurden.
- </para>
- <sect2 id="zend.loader.pluginloader.usage">
- <title>Grundsätzliche Verwendung</title>
- <para>
- Nehmen wir zuerst die folgende Verzeichnis Struktur und Klassendateien an, und dass das
- oberste Verzeichnis und das Library Verzeichnis im include_path sind:
- </para>
- <programlisting language="txt"><![CDATA[
- application/
- modules/
- foo/
- views/
- helpers/
- FormLabel.php
- FormSubmit.php
- bar/
- views/
- helpers/
- FormSubmit.php
- library/
- Zend/
- View/
- Helper/
- FormLabel.php
- FormSubmit.php
- FormText.php
- ]]></programlisting>
- <para>
- Jetzt wird ein Plugin Lader erstellt um die verschiedenen vorhandenene View Helfer
- Repositories anzusprechen:
- </para>
- <programlisting language="php"><![CDATA[
- $loader = new Zend_Loader_PluginLoader();
- $loader->addPrefixPath('Zend_View_Helper', 'Zend/View/Helper/')
- ->addPrefixPath('Foo_View_Helper',
- 'application/modules/foo/views/helpers')
- ->addPrefixPath('Bar_View_Helper',
- 'application/modules/bar/views/helpers');
- ]]></programlisting>
- <para>
- Anschließend kann ein gegebener View Helfer geladen werden indem nur der Teil des
- Klassennamens verwendet wird der dem Präfix folgt wie er definiert wurde als die Pfade
- hinzugefügt wurden:
- </para>
- <programlisting language="php"><![CDATA[
- // lädt den 'FormText' Helfer:
- $formTextClass = $loader->load('FormText'); // 'Zend_View_Helper_FormText';
- // lädt den 'FormLabel' Helfer:
- $formLabelClass = $loader->load('FormLabel'); // 'Foo_View_Helper_FormLabel'
- // lädt den 'FormSubmit' Helfer:
- $formSubmitClass = $loader->load('FormSubmit'); // 'Bar_View_Helper_FormSubmit'
- ]]></programlisting>
- <para>
- Sobald die Klasse geladen wurde, kann diese Instanziiert werden.
- </para>
- <note>
- <title>Mehrere Pfade können für einen gegebenen Präfix registriert werden</title>
- <para>
- In einigen Fällen kann es gewünscht sein den gleichen Präfix für mehrere Pfade zu
- verwenden. <classname>Zend_Loader_PluginLoader</classname> registriert aktuell ein
- Array von Pfaden für jeden gegebenen Präfix; der zuletzt resistrierte wird als erste
- geprüft. Das ist teilweise nützlich wenn Inkubator Komponenten verwendet werden.
- </para>
- </note>
- <note>
- <para>
- Optional kann ein Array von Präfix / Pfad Paaren angegeben werden (oder Präfix /
- Pfade -- Plural, Pfade sind erlaubt) und als Parameter dem Kontruktor übergeben
- werden:
- </para>
- <programlisting language="php"><![CDATA[
- $loader = new Zend_Loader_PluginLoader(array(
- 'Zend_View_Helper' => 'Zend/View/Helper/',
- 'Foo_View_Helper' => 'application/modules/foo/views/helpers',
- 'Bar_View_Helper' => 'application/modules/bar/views/helpers'
- ));
- ]]></programlisting>
- </note>
- <para>
- <classname>Zend_Loader_PluginLoader</classname> erlaubt es auch optional Plugins über
- Plugin-fähige Objekte zu teilen, ohne das eine Singleton Instanz verwendet werden muß.
- Das wird durch eine statische Registrierung ermöglicht. Der Name des Registry muß bei
- der Instanziierung als zweiter Parameter an den Konstruktor übergeben werden:
- </para>
- <programlisting language="php"><![CDATA[
- // Speichere Plugins in der statischen Registry 'foobar':
- $loader = new Zend_Loader_PluginLoader(array(), 'foobar');
- ]]></programlisting>
- <para>
- Andere Komponenten die den <classname>PluginLoader</classname> instanziieren un den
- gleichen Registry Namen verwenden haben dann Zugriff auf bereits geladene Pfade und
- Plugins.
- </para>
- </sect2>
- <sect2 id="zend.loader.pluginloader.paths">
- <title>Plugin Pfade manipulieren</title>
- <para>
- Das Beispiel der vorherigen Sektion zeigt wie Pfade zu einem Plugin Loader hinzugefügt
- werden können. Aber was kann getan werden um herauszufinden ob ein Pfad bereits geladen,
- entfernt oder anderes wurde?
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <methodname>getPaths($prefix = null)</methodname> gibt alle Pfade als Präfix /
- Pfad Paare zurück wenn kein <varname>$prefix</varname> angegeben wurde, oder nur
- die registrierten Pfade für einen gegebenen Präfix wenn ein
- <varname>$prefix</varname> vorhanden ist.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>clearPaths($prefix = null)</methodname> löscht standardmäßig alle
- registrierten Pfade, oder nur die mit einem gegebenen Präfix assoziierten, wenn
- <varname>$prefix</varname> angegeben wurde und dieser im Stack vorhanden ist.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>removePrefixPath($prefix, $path = null)</methodname> erlaubt das
- selektive löschen eines speziellen Pfades der mit einem gegebenen Präfix
- assoziiert ist. Wenn <varname>$path</varname> nicht angegeben wurde, werden alle
- Pfade für diesen Präfix entfernt. Wenn <varname>$path</varname> angegeben wurde
- und dieser für den Präfix existiert, dann wird nur dieser Pfad entfernt.
- </para>
- </listitem>
- </itemizedlist>
- </sect2>
- <sect2 id="zend.loader.pluginloader.checks">
- <title>Testen auf Plugins und Klassennamen erhalten</title>
- <para>
- Hier und da soll einfach eruiert werden ob eine Pluginklasse bereits geladen wurde bevor
- eine Aktion ausgeführt wird. <methodname>isLoaded()</methodname> nimmt einen Pluginnamen
- und gibt den Status zurück.
- </para>
- <para>
- Ein anderer üblicher Fall für das <classname>PluginLoader</classname> ist das eruieren
- des voll qualifizierten Plugin Klassennamens von geladenen Klassen;
- <methodname>getClassName()</methodname> bietet diese Funktionalität. Typischerweise wird
- dieses in Verbindung mit <methodname>isLoaded()</methodname> verwendet:
- </para>
- <programlisting language="php"><![CDATA[
- if ($loader->isLoaded('Adapter')) {
- $class = $loader->getClassName('Adapter');
- $adapter = call_user_func(array($class, 'getInstance'));
- }
- ]]></programlisting>
- </sect2>
- <sect2 id="zend.loader.pluginloader.performance">
- <title>Bessere Performance für Plugins erhalten</title>
- <para>
- Das Laden von Plugins kann eine teure Operation sein. Im Innersten muß es durch jeden
- Präfix springen, dann durch jeden Pfad dieses Präfixes, solange bis es eine passende
- Datei findet -- und welche die erwartete Klasse definiert. In Fällen wo die Datei
- existiert aber die Klasse nicht definiert ist, wird ein Fehler auf dem
- <acronym>PHP</acronym> Fehlerstack hinzugefügt, was auch eine teure Operation ist. Die
- Frage die sich stellt lautet also: Wie kann man die Flexibilität der Plugins behalten
- und auch die Performance sicherstellen?
- </para>
- <para>
- <classname>Zend_Loader_PluginLoader</classname> bietet ein optional einschaltbares
- Feature für genau diese Situation, einen integrierten Cache für die Klassendateien. Wenn
- er aktiviert wird, erstellt er eine Datei die alle erfolgreichen Includes enthält welche
- dann von der Bootstrap Datei aus aufgerufen werden kann. Durch Verwendung dieser
- Strategie, kann die Performance für Produktive Server sehr stark verbessert werden.
- </para>
- <example id="zend.loader.pluginloader.performance.example">
- <title>Verwendung des integrierten Klassendatei Caches des PluginLoaders</title>
- <para>
- Um den integrierten Klassendatei Cache zu verwenden muß einfach der folgende Code in
- die Bootstrap Datei eingefügt werden:
- </para>
- <programlisting language="php"><![CDATA[
- $classFileIncCache = APPLICATION_PATH . '/../data/pluginLoaderCache.php';
- if (file_exists($classFileIncCache)) {
- include_once $classFileIncCache;
- }
- Zend_Loader_PluginLoader::setIncludeFileCache($classFileIncCache);
- ]]></programlisting>
- <para>
- Natürlich, veriiert der Pfad und der Dateiname basieren auf den eigenen
- Bedürfnissen. Dieser Code sollte so früh wie möglich vorhanden sein um
- sicherzustellen das Plugin-basierende Komponenten davon Verwendung machen können.
- </para>
- <para>
- Wärend der Entwicklung kann es gewünscht sein den Cache auszuschalten. Eine Methode
- um das zu tun ist die Verwendung eines Konfigurationsschlüsses um festzustellen ob
- der PluginLoader cachen soll oder nicht.
- </para>
- <programlisting language="php"><![CDATA[
- $classFileIncCache = APPLICATION_PATH . '/../data/pluginLoaderCache.php';
- if (file_exists($classFileIncCache)) {
- include_once $classFileIncCache;
- }
- if ($config->enablePluginLoaderCache) {
- Zend_Loader_PluginLoader::setIncludeFileCache($classFileIncCache);
- }
- ]]></programlisting>
- <para>
- Diese Technik erlaubt es die Änderungen in der Konfigurationsdatei zu belassen und
- nicht im Code.
- </para>
- </example>
- </sect2>
- </sect1>
|