Zend_Loader-PluginLoader.xml 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- EN-Revision: 24249 -->
  3. <!-- Reviewed: no -->
  4. <sect1 id="zend.loader.pluginloader">
  5. <title>Chargeur de Plugins</title>
  6. <para>
  7. Zend Framework vous propose l'utilisation de composants "pluggables", que vous créez
  8. vous même. Ceux-ci ne sont pas forcément dans l'include_path. De même, ils ne suivent pas
  9. forcément les mêmes règles de nommage que les composants de Zend
  10. Framework.<classname>Zend_Loader_PluginLoader</classname> propose une solution à ce
  11. problème.
  12. </para>
  13. <para>
  14. <code>PluginLoader</code> suit la convention "une classe par fichier" et les tirets
  15. bas sont utilisés comme séparateurs de dossiers. Il accepte aussi qu'un préfixe optionnel
  16. lui soit passé, afin de charger une classe. Tous les chemins sont analysés en ordre LIFO.
  17. Grâce à ces deux spécificités, vous pouvez "namespacer" vos plugins, et écraser les plugins
  18. enregistrés plus tôt.
  19. </para>
  20. <sect2 id="zend.loader.pluginloader.usage">
  21. <title>Utilisation basique</title>
  22. <para>
  23. Même si nous parlons de "plugins", ce n'est pas réservé aux plugins de contrôleur
  24. frontal, mais bien à toute classe étant utilisée avec Zend Framework. Imaginons une
  25. structure de répertoires comme suit, dans laquelle les dossiers "application" et
  26. "library" sont dans l'include_path :
  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. Maintenant créons un chargeur de plugins pour utiliser les différentes classes
  50. d'aides de vue :
  51. </para>
  52. <programlisting language="php"><![CDATA[
  53. $loader = new Zend_Loader_PluginLoader();
  54. $loader->addPrefixPath('Zend_View_Helper',
  55. 'Zend/View/Helper/')
  56. ->addPrefixPath('Foo_View_Helper',
  57. 'application/modules/foo/views/helpers')
  58. ->addPrefixPath('Bar_View_Helper',
  59. 'application/modules/bar/views/helpers');
  60. ]]></programlisting>
  61. <para>
  62. Il devient alors possible de charger une aide de vue en spécifiant juste le nom de
  63. sa classe :
  64. </para>
  65. <programlisting language="php"><![CDATA[
  66. // charge l'aide 'FormText' :
  67. $formTextClass = $loader->load('FormText');
  68. // 'Zend_View_Helper_FormText'
  69. // charge l'aide 'FormLabel' :
  70. $formLabelClass = $loader->load('FormLabel');
  71. // 'Foo_View_Helper_FormLabel'
  72. // charge l'aide 'FormSubmit' :
  73. $formSubmitClass = $loader->load('FormSubmit');
  74. // 'Bar_View_Helper_FormSubmit'
  75. ]]></programlisting>
  76. <para>Une fois chargée, la classe devient instanciable.</para>
  77. <note>
  78. <title>Plusieurs dossiers peuvent être assignés à un même préfixe</title>
  79. <para>
  80. Vous pouvez "namespacer" vos composants en enregistrant plusieurs chemins pour
  81. un même préfixe.<classname>Zend_Loader_PluginLoader</classname> cherchera alors en
  82. ordre LIFO (dernier arrivé, premier sorti). Ceci est pratique pour court-circuiter
  83. ses composants et utiliser ceux en incubateur, par exemple.
  84. </para>
  85. </note>
  86. <note>
  87. <title>Paramétrage des chemins dans le constructeur</title>
  88. <para>
  89. En constructeur, passez un tableau de paires prefix / path ou prefix / paths
  90. -- plusieurs dossiers par préfixe :
  91. </para>
  92. <programlisting language="php"><![CDATA[
  93. $loader = new Zend_Loader_PluginLoader(array(
  94. 'Zend_View_Helper' => 'Zend/View/Helper/',
  95. 'Foo_View_Helper' => 'application/modules/foo/views/helpers',
  96. 'Bar_View_Helper' => 'application/modules/bar/views/helpers'
  97. ));
  98. ]]></programlisting>
  99. </note>
  100. <para>
  101. <classname>Zend_Loader_PluginLoader</classname> peut aussi permettre de partager
  102. des plugins grâce au registre. Indiquez le nom du registre de cette manière :
  103. </para>
  104. <programlisting language="php"><![CDATA[
  105. // Stocke les plugins dans le registre à l'index 'foobar':
  106. $loader = new Zend_Loader_PluginLoader(array(), 'foobar');
  107. ]]></programlisting>
  108. <para>
  109. Si un autre composant instancie le <code>PluginLoader</code> en utilisant le même
  110. nom de registre, alors tous les chemins et plugins déjà chargés seront
  111. disponibles.
  112. </para>
  113. </sect2>
  114. <sect2 id="zend.loader.pluginloader.paths">
  115. <title>Manipulation des chemins des Plugins</title>
  116. <para>
  117. Pour afficher ou supprimer des chemins déjà enregistrés, utilisez l'une des
  118. méthodes suivantes :
  119. </para>
  120. <itemizedlist>
  121. <listitem>
  122. <para>
  123. <methodname>getPaths($prefix = null)</methodname> retourne les chemin sous la forme
  124. prefix / path si <varname>$prefix</varname> n'est pas renseigné. Sinon, ce sont les
  125. chemins enregistrés pour le préfixe en question qui sont renvoyés.
  126. </para>
  127. </listitem>
  128. <listitem>
  129. <para>
  130. <methodname>clearPaths($prefix = null)</methodname> va effacer tous les chemins. Si
  131. <varname>$prefix</varname> est passé, ce sont les chemins correspondants à ce préfixe
  132. qui seront supprimés.
  133. </para>
  134. </listitem>
  135. <listitem>
  136. <para>
  137. <methodname>removePrefixPath($prefix, $path = null)</methodname> permet de supprimer
  138. un chemin précis, d'un préfixe spécifié. Si <varname>$path</varname> n'est pas
  139. renseigné, tous les chemins du préfixe seront effacés.
  140. </para>
  141. </listitem>
  142. </itemizedlist>
  143. </sect2>
  144. <sect2 id="zend.loader.pluginloader.checks">
  145. <title>Test des Plugins et récupération des noms de classe</title>
  146. <para>
  147. Lorsque vous voulez savoir si une classe de plugin a été chargée,
  148. <methodname>isLoaded()</methodname> prend en paramètre le nom du plugin, et retourne sont
  149. statut.
  150. </para>
  151. <para>
  152. Une autre utilisation de <code>PluginLoader</code> peut être de récupérer le nom
  153. des classes des plugins chargés.<methodname>getClassName()</methodname> vous le permet. Utilisée en
  154. conjonction avec <methodname>isLoaded()</methodname>, vous pouvez écrire par exemple ceci :
  155. </para>
  156. <programlisting language="php"><![CDATA[
  157. if ($loader->isLoaded('Adapter')) {
  158. $class = $loader->getClassName('Adapter');
  159. $adapter = call_user_func(array($class, 'getInstance'));
  160. }
  161. ]]></programlisting>
  162. </sect2>
  163. <sect2 id="zend.loader.pluginloader.performance">
  164. <title>Obtenir de meilleures performances avec les Plugins</title>
  165. <para>
  166. Le chargement des plugins peut être une opération consommatrice en ressources. En
  167. interne, il doit parcourir chaque préfixe, ainsi que chaque chemin dans ce préfixe
  168. jusqu'à ce qu'il trouve un fichier qui correspond - et qui définit de plus la classe
  169. voulue. Dans le cas où le fichier existe mais ne défini pas la classe, une erreur sera
  170. ajouté à la pile d'erreur <acronym>PHP</acronym>, opération qui est elle aussi consommatrice. La question
  171. qui vient à l'esprit est : comment maintenir la flexibilité des plugins et la
  172. performance ?
  173. </para>
  174. <para>
  175. <classname>Zend_Loader_PluginLoader</classname> offre une fonctionnalité intégrée
  176. pour ce cas, un fichier de cache des inclusions de classe. Quand il est activé, ceci
  177. crée un fichier qui contient toutes les inclusions qui ont fonctionnées et qui peuvent
  178. donc être appelées dans votre fichier d'initialisation. En utilisant ceci, vous pouvez
  179. considérablement accroître les performances de vos serveurs de production.
  180. </para>
  181. <example id="zend.loader.pluginloader.performance.example">
  182. <title>Utilisation du fichier de cache des inclusions de classe de
  183. PluginLoader</title>
  184. <para>
  185. Pour utiliser le fichier de cache des inclusions de classe, collez simplement
  186. le code suivant dans votre fichier d'initialisation :
  187. </para>
  188. <programlisting language="php"><![CDATA[
  189. $classFileIncCache = APPLICATION_PATH . '/../data/pluginLoaderCache.php';
  190. if (file_exists($classFileIncCache)) {
  191. include_once $classFileIncCache;
  192. }
  193. Zend_Loader_PluginLoader::setIncludeFileCache($classFileIncCache);
  194. ]]></programlisting>
  195. <para>
  196. Évidemment, le chemin et le fichier varieront en fonction de vos besoins. Ce
  197. code doit intervenir aussi vite que possible, pour s'assurer que tous les composants
  198. à base de plugins pourront l'utiliser.
  199. </para>
  200. <para>
  201. En cours du développement, vous pouvez souhaiter désactiver le cache. Une
  202. méthode permettant ceci est d'utiliser une clé de configuration pour déterminer ou
  203. non si le chargeur de plugins doit mettre les informations en cache.
  204. </para>
  205. <programlisting language="php"><![CDATA[
  206. $classFileIncCache = APPLICATION_PATH . '/../data/pluginLoaderCache.php';
  207. if (file_exists($classFileIncCache)) {
  208. include_once $classFileIncCache;
  209. }
  210. if ($config->enablePluginLoaderCache) {
  211. Zend_Loader_PluginLoader::setIncludeFileCache($classFileIncCache);
  212. }
  213. ]]></programlisting>
  214. <para>
  215. Cette technique vous permet de restreindre les modifications au seul fichier
  216. de configuration plutôt que dans votre code.
  217. </para>
  218. </example>
  219. </sect2>
  220. </sect1>