| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 15617 -->
- <!-- 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 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 <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 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 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 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>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|