Zend_Loader-PluginLoader.xml 9.3 KB

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