2
0

Zend_Loader-PluginLoader.xml 11 KB

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