Zend_Loader-PluginLoader.xml 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- EN-Revision: 15156 -->
  3. <!-- Reviewed: no -->
  4. <sect1 id="zend.loader.pluginloader">
  5. <title>Plugins laden</title>
  6. <para>
  7. Eine Anzahl von Zend Framework Komponenten ist steckbar, und erlaubt es Funktionen dynamisch zu laden
  8. durch die Angabe eines Klassenpräfixes und einem Pfad zu den Klassendaten die nicht notwendigerweise im
  9. <code>include_path</code> sind, oder nicht notwendigerweise den traditionellen Namenskonventionen
  10. folgen. <classname>Zend_Loader_PluginLoader</classname> bietet übliche Funktionalitäten für diesen Prozess.
  11. </para>
  12. <para>
  13. Die grundsätzliche Verwendung vom <code>PluginLoader</code> folgt den Namenskonventionen vom Zend
  14. Framework mit einer Klasse pro Datei, der Verwendung von Unterstrichen als Verzeichnistrenner bei der
  15. Auflösung von Pfaden. Es erlaubt die Übergabe eines optionalen Klasenpräfixes der vorangestellt wird,
  16. wenn eine bestimmte Pluginklasse geladen wird. Zusätzlich können Pfade in LIFO Reihenfolge durchsucht
  17. werden. Die LIFO Suche und der Klassen Präfix erlaubt es für die Plugins Namensräumen zu definieren,
  18. und auf diese Weise Plugins zu überladen die vorher registriert wurden.
  19. </para>
  20. <sect2 id="zend.loader.pluginloader.usage">
  21. <title>Grundsätzliche Verwendung</title>
  22. <para>
  23. Nehmen wir zuerst die folgende Verzeichnis Struktur und Klassendateien an, und das das oberste
  24. Verzeichnis und das Library Verzeichnis im include_path sind:
  25. </para>
  26. <programlisting role="txt"><![CDATA[
  27. application/
  28. modules/
  29. foo/
  30. views/
  31. helpers/
  32. FormLabel.php
  33. FormSubmit.php
  34. bar/
  35. views/
  36. helpers/
  37. FormSubmit.php
  38. library/
  39. Zend/
  40. View/
  41. Helper/
  42. FormLabel.php
  43. FormSubmit.php
  44. FormText.php
  45. ]]>
  46. </programlisting>
  47. <para>
  48. Jetzt wird ein Plugin Lader erstellt um die verschiedenen vorhandenene View Helfer Repositories
  49. anzusprechen:
  50. </para>
  51. <programlisting role="php"><![CDATA[
  52. $loader = new Zend_Loader_PluginLoader();
  53. $loader->addPrefixPath('Zend_View_Helper', 'Zend/View/Helper/')
  54. ->addPrefixPath('Foo_View_Helper',
  55. 'application/modules/foo/views/helpers')
  56. ->addPrefixPath('Bar_View_Helper',
  57. 'application/modules/bar/views/helpers');
  58. ]]></programlisting>
  59. <para>
  60. Anschließend kann ein gegebener View Helfer geladen werden indem nur der Teil des Klassennamens
  61. verwendet wird der dem Präfix folgt wie er definiert wurde als die Pfade hinzugefügt wurden:
  62. </para>
  63. <programlisting role="php"><![CDATA[
  64. // lädt den 'FormText' Helfer:
  65. $formTextClass = $loader->load('FormText'); // 'Zend_View_Helper_FormText';
  66. // lädt den 'FormLabel' Helfer:
  67. $formLabelClass = $loader->load('FormLabel'); // 'Foo_View_Helper_FormLabel'
  68. // lädt den 'FormSubmit' Helfer:
  69. $formSubmitClass = $loader->load('FormSubmit'); // 'Bar_View_Helper_FormSubmit'
  70. ]]></programlisting>
  71. <para>
  72. Sobald die Klasse geladen wurde, kann diese Instanziiert werden.
  73. </para>
  74. <note>
  75. <title>Mehrere Pfade können für einen gegebenen Präfix registriert werden</title>
  76. <para>
  77. In einigen Fällen kann es gewünscht sein den gleichen Präfix für mehrere Pfade zu verwenden.
  78. <classname>Zend_Loader_PluginLoader</classname> registriert aktuell ein Array von Pfaden für jeden
  79. gegebenen Präfix; der zuletzt resistrierte wird als erste geprüft. Das ist teilweise nützlich
  80. wenn Inkubator Komponenten verwendet werden.
  81. </para>
  82. </note>
  83. <note>
  84. <para>
  85. Optional kann ein Array von Präfix / Pfad Paaren angegeben werden (oder Präfix / Pfade --
  86. Plural, Pfade sind erlaubt) und als Parameter dem Kontruktor übergeben werden:
  87. </para>
  88. <programlisting role="php"><![CDATA[
  89. $loader = new Zend_Loader_PluginLoader(array(
  90. 'Zend_View_Helper' => 'Zend/View/Helper/',
  91. 'Foo_View_Helper' => 'application/modules/foo/views/helpers',
  92. 'Bar_View_Helper' => 'application/modules/bar/views/helpers'
  93. ));
  94. ]]></programlisting>
  95. </note>
  96. <para>
  97. <classname>Zend_Loader_PluginLoader</classname> erlaubt es auch optional Plugins über Plugin-fähige Objekte
  98. zu teilen, ohne das eine Singleton Instanz verwendet werden muß. Das wird durch eine statische
  99. Registrierung ermöglicht. Der Name des Registry muß bei der Instanziierung als zweiter Parameter
  100. an den Konstruktor übergeben werden:
  101. </para>
  102. <programlisting role="php"><![CDATA[
  103. // Speichere Plugins in der statischen Registry 'foobar':
  104. $loader = new Zend_Loader_PluginLoader(array(), 'foobar');
  105. ]]></programlisting>
  106. <para>
  107. Andere Komponenten die den <code>PluginLoader</code> instanziieren un dden gleichen Registry Namen
  108. verwenden haben dann Zugriff auf bereits geladene Pfade und Plugins.
  109. </para>
  110. </sect2>
  111. <sect2 id="zend.loader.pluginloader.paths">
  112. <title>Plugin Pfade manipulieren</title>
  113. <para>
  114. Das Beispiel der vorherigen Sektion zeigt wie Pfade zu einem Plugin Loader hinzugefügt werden können.
  115. Aber was kann getan werden um herauszufinden ob ein Pfad bereits geladen, entfernt oder anderes wurde?
  116. </para>
  117. <itemizedlist>
  118. <listitem>
  119. <para>
  120. <code>getPaths($prefix = null)</code> gibt alle Pfade als Präfix / Pfad Paare zurück wenn
  121. kein <code>$prefix</code> angegeben wurde, oder nur die registrierten Pfade für einen
  122. gegebenen Präfix wenn ein <code>$prefix</code> vorhanden ist.
  123. </para>
  124. </listitem>
  125. <listitem>
  126. <para>
  127. <code>clearPaths($prefix = null)</code> löscht standardmäßig alle registrierten Pfade,
  128. oder nur die mit einem gegebenen Präfix assoziierten, wenn <code>$prefix</code> angegeben
  129. wurde und dieser im Stack vorhanden ist.
  130. </para>
  131. </listitem>
  132. <listitem>
  133. <para>
  134. <code>removePrefixPath($prefix, $path = null)</code> erlaubt das selektive löschen eines
  135. speziellen Pfades der mit einem gegebenen Präfix assoziiert ist. Wenn <code>$path</code>
  136. nicht angegeben wurde, werden alle Pfade für diesen Präfix entfernt. Wenn <code>$path</code>
  137. angegeben wurde und dieser für den Präfix existiert, dann wird nur dieser Pfad entfernt.
  138. </para>
  139. </listitem>
  140. </itemizedlist>
  141. </sect2>
  142. <sect2 id="zend.loader.pluginloader.checks">
  143. <title>Testen auf Plugins und Klassennamen erhalten</title>
  144. <para>
  145. Hier und da soll einfach eruiert werden ob eine Pluginklasse bereits geladen wurde bevor eine
  146. Aktion ausgeführt wird. <code>isLoaded()</code> nimmt einen Pluginnamen und gibt den Status zurück.
  147. </para>
  148. <para>
  149. Ein anderer üblicher Fall für das <code>PluginLoader</code> ist das eruieren des voll qualifizierten
  150. Plugin Klassennamens von geladenen Klassen; <code>getClassName()</code> bietet diese Funktionalität.
  151. Typischerweise wird dieses in Verbindung mit <code>isLoaded()</code> verwendet:
  152. </para>
  153. <programlisting role="php"><![CDATA[
  154. if ($loader->isLoaded('Adapter')) {
  155. $class = $loader->getClassName('Adapter');
  156. $adapter = call_user_func(array($class, 'getInstance'));
  157. }
  158. ]]></programlisting>
  159. </sect2>
  160. <sect2 id="zend.loader.pluginloader.performance">
  161. <title>Bessere Performance für Plugins erhalten</title>
  162. <para>
  163. Das Laden von Plugins kann eine teure Operation sein. Im Innersten muß es durch jeden Präfix
  164. springen, dann durch jeden Pfad dieses Präfixes, solange bis es eine passende Datei findet --
  165. und welche die erwartete Klasse definiert. In Fällen wo die Datei existiert aber die Klasse
  166. nicht definiert ist, wird ein Fehler auf dem PHP Fehlerstack hinzugefügt, was auch eine
  167. teure Operation ist. Die Frage die sich stellt lautet also: Wie kann man die Flexibilität der
  168. Plugins behalten und auch die Performance sicherstellen?
  169. </para>
  170. <para>
  171. <classname>Zend_Loader_PluginLoader</classname> bietet ein optional einschaltbares Feature für genau diese
  172. Situation, einen integrierten Cache für die Klassendateien. Wenn er aktiviert wird, erstellt er
  173. eine Datei die alle erfolgreichen Includes enthält welche dann von der Bootstrap Datei aus
  174. aufgerufen werden kann. Durch Verwendung dieser Strategie, kann die Performance für
  175. Produktive Server sehr stark verbessert werden.
  176. </para>
  177. <example id="zend.loader.pluginloader.performance.example">
  178. <title>Verwendung des integrierten Klassendatei Caches des PluginLoaders</title>
  179. <para>
  180. Um den integrierten Klassendatei Cache zu verwenden muß einfach der folgende Code in die
  181. Bootstrap Datei eingefügt werden:
  182. </para>
  183. <programlisting role="php"><![CDATA[
  184. $classFileIncCache = APPLICATION_PATH . '/../data/pluginLoaderCache.php';
  185. if (file_exists($classFileIncCache)) {
  186. include_once $classFileIncCache;
  187. }
  188. Zend_Loader_PluginLoader::setIncludeFileCache($classFileIncCache);
  189. ]]></programlisting>
  190. <para>
  191. Natürlich, veriiert der Pfad und der Dateiname basieren auf den eigenen Bedürfnissen.
  192. Dieser Code sollte so früh wie möglich vorhanden sein um sicherzustellen das
  193. Plugin-basierende Komponenten davon Verwendung machen können.
  194. </para>
  195. <para>
  196. Wärend der Entwicklung kann es gewünscht sein den Cache auszuschalten. Eine Methode um das
  197. zu tun ist die Verwendung eines Konfigurationsschlüsses um festzustellen ob der PluginLoader
  198. cachen soll oder nicht.
  199. </para>
  200. <programlisting role="php"><![CDATA[
  201. $classFileIncCache = APPLICATION_PATH . '/../data/pluginLoaderCache.php';
  202. if (file_exists($classFileIncCache)) {
  203. include_once $classFileIncCache;
  204. }
  205. if ($config->enablePluginLoaderCache) {
  206. Zend_Loader_PluginLoader::setIncludeFileCache($classFileIncCache);
  207. }
  208. ]]></programlisting>
  209. <para>
  210. Diese Technik erlaubt es die Änderungen in der Konfigurationsdatei zu belassen und nicht
  211. im Code.
  212. </para>
  213. </example>
  214. </sect2>
  215. </sect1>
  216. <!--
  217. vim:se ts=4 sw=4 et:
  218. -->