| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 15156 -->
- <!-- 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
- <code>include_path</code> 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 <code>PluginLoader</code> 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 das das oberste
- Verzeichnis und das Library Verzeichnis im include_path sind:
- </para>
- <programlisting role="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 role="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 role="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 role="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 role="php"><![CDATA[
- // Speichere Plugins in der statischen Registry 'foobar':
- $loader = new Zend_Loader_PluginLoader(array(), 'foobar');
- ]]></programlisting>
- <para>
- Andere Komponenten die den <code>PluginLoader</code> instanziieren un dden 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>
- <code>getPaths($prefix = null)</code> gibt alle Pfade als Präfix / Pfad Paare zurück wenn
- kein <code>$prefix</code> angegeben wurde, oder nur die registrierten Pfade für einen
- gegebenen Präfix wenn ein <code>$prefix</code> vorhanden ist.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>clearPaths($prefix = null)</code> löscht standardmäßig alle registrierten Pfade,
- oder nur die mit einem gegebenen Präfix assoziierten, wenn <code>$prefix</code> angegeben
- wurde und dieser im Stack vorhanden ist.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>removePrefixPath($prefix, $path = null)</code> erlaubt das selektive löschen eines
- speziellen Pfades der mit einem gegebenen Präfix assoziiert ist. Wenn <code>$path</code>
- nicht angegeben wurde, werden alle Pfade für diesen Präfix entfernt. Wenn <code>$path</code>
- 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. <code>isLoaded()</code> nimmt einen Pluginnamen und gibt den Status zurück.
- </para>
- <para>
- Ein anderer üblicher Fall für das <code>PluginLoader</code> ist das eruieren des voll qualifizierten
- Plugin Klassennamens von geladenen Klassen; <code>getClassName()</code> bietet diese Funktionalität.
- Typischerweise wird dieses in Verbindung mit <code>isLoaded()</code> verwendet:
- </para>
- <programlisting role="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 PHP 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 role="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 role="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>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|