File: Zend_Loader-PluginLoader.xml

package info (click to toggle)
zendframework 1.12.9%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: jessie-kfreebsd
  • size: 133,584 kB
  • sloc: xml: 1,311,829; php: 570,173; sh: 170; makefile: 125; sql: 121
file content (259 lines) | stat: -rw-r--r-- 10,500 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
<?xml version="1.0" encoding="UTF-8"?>
<!-- EN-Revision: 24249 -->
<!-- Reviewed: no -->
<sect1 id="zend.loader.pluginloader">
    <title>Chargeur de Plugins</title>

    <para>
        Zend Framework vous propose l'utilisation de composants "pluggables", que vous créez
        vous même. Ceux-ci ne 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 composants de Zend
        Framework.<classname>Zend_Loader_PluginLoader</classname> propose une solution à ce
        problème.
    </para>

    <para>
        <code>PluginLoader</code> suit la convention "une classe par fichier" et les tirets
        bas sont utilisés comme séparateurs de dossiers. Il accepte aussi qu'un préfixe optionnel
        lui soit passé, afin de charger une classe. Tous les chemins sont analysés en ordre LIFO.
        Grâce à ces deux spécificités, vous pouvez "namespacer" vos plugins, et écraser les plugins
        enregistrés plus tôt.
    </para>

    <sect2 id="zend.loader.pluginloader.usage">
        <title>Utilisation basique</title>

        <para>
            Même si nous parlons de "plugins", ce n'est pas réservé aux plugins de contrôleur
            frontal, mais bien à toute classe étant utilisée avec Zend Framework. Imaginons une
            structure de répertoires comme suit, dans laquelle les dossiers "application" et
            "library" sont dans l'include_path :
        </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>
            Maintenant créons un chargeur de plugins pour utiliser les différentes classes
            d'aides de vue :
        </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>
            Il devient alors possible de charger une aide de vue en spécifiant juste le nom de
            sa classe :
        </para>

        <programlisting language="php"><![CDATA[
// charge l'aide 'FormText' :
$formTextClass = $loader->load('FormText');
// 'Zend_View_Helper_FormText'

// charge l'aide 'FormLabel' :
$formLabelClass = $loader->load('FormLabel');
// 'Foo_View_Helper_FormLabel'

// charge l'aide 'FormSubmit' :
$formSubmitClass = $loader->load('FormSubmit');
// 'Bar_View_Helper_FormSubmit'
]]></programlisting>

        <para>Une fois chargée, la classe devient instanciable.</para>

        <note>
            <title>Plusieurs dossiers peuvent être assignés à un même préfixe</title>

            <para>
                Vous pouvez "namespacer" vos composants en enregistrant plusieurs chemins pour
                un même préfixe.<classname>Zend_Loader_PluginLoader</classname> cherchera alors en
                ordre LIFO (dernier arrivé, premier sorti). Ceci est pratique pour court-circuiter
                ses composants et utiliser ceux en incubateur, par exemple.
            </para>
        </note>

        <note>
            <title>Paramétrage des chemins dans le constructeur</title>

            <para>
                En constructeur, passez un tableau de paires prefix / path ou prefix / paths
                -- plusieurs dossiers par préfixe :
            </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> peut aussi permettre de partager
            des plugins grâce au registre. Indiquez le nom du registre de cette manière :
        </para>

        <programlisting language="php"><![CDATA[
// Stocke les plugins dans le registre à l'index 'foobar':
$loader = new Zend_Loader_PluginLoader(array(), 'foobar');
]]></programlisting>

        <para>
            Si un autre composant instancie le <code>PluginLoader</code> en utilisant le même
            nom de registre, alors tous les chemins et plugins déjà chargés seront
            disponibles.
        </para>
    </sect2>

    <sect2 id="zend.loader.pluginloader.paths">
        <title>Manipulation des chemins des Plugins</title>

        <para>
            Pour afficher ou supprimer des chemins déjà enregistrés, utilisez l'une des
            méthodes suivantes :
        </para>

        <itemizedlist>
            <listitem>
                <para>
                    <methodname>getPaths($prefix = null)</methodname> retourne les chemin sous la forme
                    prefix / path si <varname>$prefix</varname> n'est pas renseigné. Sinon, ce sont les
                    chemins enregistrés pour le préfixe en question qui sont renvoyés.
                </para>
            </listitem>

            <listitem>
                <para>
                    <methodname>clearPaths($prefix = null)</methodname> va effacer tous les chemins. Si
                    <varname>$prefix</varname> est passé, ce sont les chemins correspondants à ce préfixe
                    qui seront supprimés.
                </para>
            </listitem>

            <listitem>
                <para>
                    <methodname>removePrefixPath($prefix, $path = null)</methodname> permet de supprimer
                    un chemin précis, d'un préfixe spécifié. Si <varname>$path</varname> n'est pas
                    renseigné, tous les chemins du préfixe seront effacés.
                </para>
            </listitem>
        </itemizedlist>
    </sect2>

    <sect2 id="zend.loader.pluginloader.checks">
        <title>Test des Plugins et récupération des noms de classe</title>

        <para>
            Lorsque vous voulez savoir si une classe de plugin a été chargée,
            <methodname>isLoaded()</methodname> prend en paramètre le nom du plugin, et retourne sont
            statut.
        </para>

        <para>
            Une autre utilisation de <code>PluginLoader</code> peut être de récupérer le nom
            des classes des plugins chargés.<methodname>getClassName()</methodname> vous le permet. Utilisée en
            conjonction avec <methodname>isLoaded()</methodname>, vous pouvez écrire par exemple ceci :
        </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>Obtenir de meilleures performances avec les Plugins</title>

        <para>
            Le chargement des plugins peut être une opération consommatrice en ressources. En
            interne, il doit parcourir chaque préfixe, ainsi que chaque chemin dans ce préfixe
            jusqu'à ce qu'il trouve un fichier qui correspond - et qui définit de plus la classe
            voulue. Dans le cas où le fichier existe mais ne défini pas la classe, une erreur sera
            ajouté à la pile d'erreur <acronym>PHP</acronym>, opération qui est elle aussi consommatrice. La question
            qui vient à l'esprit est : comment maintenir la flexibilité des plugins et la
            performance ?
        </para>

        <para>
            <classname>Zend_Loader_PluginLoader</classname> offre une fonctionnalité intégrée
            pour ce cas, un fichier de cache des inclusions de classe. Quand il est activé, ceci
            crée un fichier qui contient toutes les inclusions qui ont fonctionnées et qui peuvent
            donc être appelées dans votre fichier d'initialisation. En utilisant ceci, vous pouvez
            considérablement accroître les performances de vos serveurs de production.
        </para>

        <example id="zend.loader.pluginloader.performance.example">
            <title>Utilisation du fichier de cache des inclusions de classe de
            PluginLoader</title>

            <para>
                Pour utiliser le fichier de cache des inclusions de classe, collez simplement
                le code suivant dans votre fichier d'initialisation :
            </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>
                Évidemment, le chemin et le fichier varieront en fonction de vos besoins. Ce
                code doit intervenir aussi vite que possible, pour s'assurer que tous les composants
                à base de plugins pourront l'utiliser.
            </para>

            <para>
                En cours du développement, vous pouvez souhaiter désactiver le cache. Une
                méthode permettant ceci est d'utiliser une clé de configuration pour déterminer ou
                non si le chargeur de plugins doit mettre les informations en cache.
            </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>
                Cette technique vous permet de restreindre les modifications au seul fichier
                de configuration plutôt que dans votre code.
            </para>
        </example>
    </sect2>
</sect1>