| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618 |
- <?xml version="1.0" encoding="utf-8"?>
- <!-- EN-Revision: 24249 -->
- <!-- Reviewed: no -->
- <sect1 id="zend.controller.action">
- <title>Contrôleurs d'action</title>
- <sect2 id="zend.controller.action.introduction">
- <title>Introduction</title>
- <para>
- <classname>Zend_Controller_Action</classname> est une classe abstraite que vous
- pouvez utiliser avec le contrôleur frontal quand vous construisez un site Web basé sur
- le modèle de conception Modèle-Vues-Contrôleurs (<acronym>MVC</acronym>).
- </para>
- <para>
- Pour utiliser <classname>Zend_Controller_Action</classname>, vous devez la
- sous-classer dans vos propres classes de contrôleurs d'action (ou la sous-classer pour
- créer votre propre classe de base pour vos contrôleurs d'action). L'opération la plus
- basique est de la sous-classer, et de créer vos méthodes d'action qui correspondent aux
- différentes actions que vous souhaitez gérer. La gestion du routage et de la
- distribution des <classname>Zend_Controller</classname> va rechercher automatiquement
- les méthodes dont le nom termine par 'Action' dans votre classe et les considérer comme
- des actions potentiellement valides de votre contrôleur.
- </para>
- <para>Par exemple, considérons une classe définie comme ceci :</para>
- <programlisting language="php"><![CDATA[
- class FooController extends Zend_Controller_Action
- {
- public function barAction()
- {
- // réalise quelquechose
- }
- public function bazAction()
- {
- // réalise quelquechose
- }
- }
- ]]></programlisting>
- <para>
- La classe <emphasis>FooController</emphasis> (contrôleur <emphasis>foo</emphasis>)
- définit deux actions, <emphasis>bar</emphasis> et <emphasis>baz</emphasis>.
- </para>
- <para>
- Il y a d'autres fonctionnalités qui peuvent être utilisées, comme personnaliser
- l'initialisation des actions, gérer les actions par défaut quand aucune action ou une
- action invalide est fournie, avoir la possibilité de hook ("détournement") en pre et
- post-dispatch, et une variété de méthodes d'aides (helper). Ce chapitre fournit une vue
- d'ensemble des fonctionnalités du contrôleur d'action.
- </para>
- <note>
- <title>Comportement par défaut</title>
- <para>
- Par défaut, le <link linkend="zend.controller.front">contrôleur frontal</link>
- active l'aide d'action
- <link linkend="zend.controller.actionhelpers.viewrenderer">ViewRenderer</link>.
- Cette aide s'occupe de l'injection automatique de l'objet de vue dans vos
- contrôleurs, ainsi que du rendu de cette vue. Vous pouvez la désactiver au sein de
- vos contrôleurs par l'une ou l'autre des actions suivantes :
- </para>
- <programlisting language="php"><![CDATA[
- class FooController extends Zend_Controller_Action
- {
- public function init()
- {
- // Locale à ce seul contrôleur ; affecte toutes les actions,
- // si chargée dans l'init :
- $this->_helper->viewRenderer->setNoRender(true);
- // Global :
- $this->_helper->removeHelper('viewRenderer');
- // Global aussi, mais doit être réalisé en conjonction avec
- // la version locale pour être propagé dans ce contrôleur:
- Zend_Controller_Front::getInstance()->setParam('noViewRenderer',
- true);
- }
- }
- ]]></programlisting>
- <para>
- Les méthodes <methodname>initView()</methodname>,
- <methodname>getViewScript()</methodname>, <methodname>render()</methodname>, et
- <methodname>renderScript()</methodname> sont affectées chacune au
- <emphasis>ViewRenderer</emphasis> à moins que l'aide ne soit pas chargée dans le
- gestionnaire d'aide (helper broker) ou que l'option
- <emphasis>noViewRenderer</emphasis> n'ait été réglée.
- </para>
- <para>
- Vous pouvez simplement désactiver le rendu pour une vue individuelle grâce au
- drapeau <emphasis>noRender</emphasis> du <emphasis>ViewRenderer</emphasis> :
- </para>
- <programlisting language="php"><![CDATA[
- class FooController extends Zend_Controller_Action
- {
- public function barAction()
- {
- // désactive le rendu automatique pour cette action seulement :
- $this->_helper->viewRenderer->setNoRender();
- }
- }
- ]]></programlisting>
- <para>
- Les raisons principales de désactiver le <emphasis>ViewRenderer</emphasis> sont
- l'absence de besoin d'objets de vues ou si vous n'effectuez pas de rendu via des
- scripts de vues (par exemple, quand vous utilisez un contrôleur d'action pour
- servir des protocoles de service Web comme <acronym>SOAP</acronym>,
- <acronym>XML-RPC</acronym>, ou <acronym>REST</acronym>). Dans la plupart
- des cas, il n'est pas nécessaire de désactiver globalement le
- <emphasis>ViewRenderer</emphasis>, seulement de manière sélective pour des
- contrôleurs ou actions individuels.
- </para>
- </note>
- </sect2>
- <sect2 id="zend.controller.action.initialization">
- <title>Initialisation d'objet</title>
- <para>
- Même si vous pouvez toujours surcharger le constructeur du contrôleur d'action,
- nous ne vous le recommandons pas.
- <methodname>Zend_Controller_Action::__construct()</methodname> réalise certaines tâches
- importantes, comme l'enregistrement des objets de requêtes et de réponses, ainsi que
- l'invocation d'arguments personnalisés fourni par le contrôleur frontal. Si vous devez
- surcharger le constructeur, n'oubliez pas d'appeler
- <methodname>parent::__construct($request, $response, $invokeArgs)</methodname>.
- </para>
- <para>
- La manière la plus appropriée de personnaliser l'instanciation est d'utiliser la
- méthode <methodname>init()</methodname>, qui est appelée en dernière tâche de
- <methodname>__construct()</methodname>. Par exemple, si vous voulez vous connecter à
- une base de données à l'instanciation :
- </para>
- <programlisting language="php"><![CDATA[
- class FooController extends Zend_Controller_Action
- {
- public function init()
- {
- $this->db = Zend_Db::factory('Pdo_Mysql', array(
- 'host' => 'myhost',
- 'username' => 'user',
- 'password' => 'XXXXXXX',
- 'dbname' => 'website'
- ));
- }
- }
- ]]></programlisting>
- </sect2>
- <sect2 id="zend.controller.action.prepostdispatch">
- <title>Détournement Pre et Post-Dispatch (Hook)</title>
- <para>
- <classname>Zend_Controller_Action</classname> spécifie deux méthodes qui peuvent être
- appelées juste avant et juste après une action, <methodname>preDispatch()</methodname>
- et <methodname>postDispatch()</methodname>. Celles-ci peuvent être pratiques dans
- plusieurs cas : vérifier l'authentification et les <acronym>ACL</acronym> avant
- d'exécuter une action (en appelant <methodname>_forward()</methodname> dans
- <methodname>preDispatch()</methodname>, l'action sera évitée), par
- exemple, ou en plaçant du contenu généré dans une partie du modèle du site
- (<methodname>postDispatch()</methodname>).
- </para>
- <note>
- <title>Utilisation de init() ou de preDispatch()</title>
- <para>
- Dans la <link linkend="zend.controller.action.initialization">section
- précédente</link>, nous avons introduit la méthode
- <methodname>init()</methodname>, et dans celle-ci, la méthode
- <methodname>preDispatch()</methodname>. Quelles sont leurs différences, et quelles
- actions vont-elles réaliser chacune ?
- </para>
- <para>
- La méthode <methodname>init()</methodname> a pour but principal d'étendre le
- constructeur. Typiquement, votre constructeur devrait simplement paramétrer les
- états des objets, mais pas réaliser d'opérations logiques. Ceci peut inclure
- l'initialisation des ressources utilisées dans le contrôleur (comme des modèles,
- des objets de configuration, etc.), ou assigner des valeurs issues du contrôleur
- frontal, du fichier d'amorçage, ou d'un registre.
- </para>
- <para>
- La méthode <methodname>preDispatch()</methodname> peut aussi être utilisée pour
- paramétrer un objet ou un environnement (par exemple, une vue, une aide d'action,
- etc.), mais son but principal est d'établir des décisions autorisant ou non une
- action requêtée à être distribuée. Si elle ne l'est pas, vous pouvez alors utiliser
- <methodname>_forward()</methodname> vers une autre action, ou lancer une exception.
- </para>
- <para>
- Note: la méthode <methodname>_forward()</methodname> s'exécutera pas correctement
- si elle est appelée depuis <methodname>init()</methodname>, ce qui est une
- formalisation des intentions de deux méthodes.
- </para>
- </note>
- </sect2>
- <sect2 id="zend.controller.action.accessors">
- <title>Accesseurs</title>
- <para>
- Un certain nombre d'objets et de variables sont enregistrés avec l'objet et chacun
- possède des méthodes accesseurs.
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>Objet Requête</emphasis> : <methodname>getRequest()</methodname>
- peut être utilisé pour récupérer l'objet de requête utilisé pour appeler
- l'action.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>Objet Réponse</emphasis> : <methodname>getResponse()</methodname>
- peut être utilisé pour récupérer l'objet de réponse assemblant la réponse
- finale. Quelques appels typiques peuvent ressembler à ceci :
- </para>
- <programlisting language="php"><![CDATA[
- $this->getResponse()->setHeader('Content-Type', 'text/xml');
- $this->getResponse()->appendBody($content);
- ]]></programlisting>
- </listitem>
- <listitem>
- <para>
- <emphasis>Arguments d'invocation</emphasis> : le contrôleur frontal peut
- transmettre des paramètres au routeur, au distributeur, et au contrôleur
- d'action. Pour récupérer individuellement ceux-ci utilisez
- <methodname>getInvokeArg($key)</methodname> ; alternativement, récupérer la
- liste entière en utilisant <methodname>getInvokeArgs()</methodname>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>Paramètres de requêtes</emphasis> : l'objet de requête
- rassemble les paramètres de requête, comme les paramètres
- <constant>_GET</constant> ou _<constant>_POST</constant>, ou les
- paramètres utilisateurs spécifiés dans le chemin d'<acronym>URL</acronym>.
- Pour récupérer ceux-ci utilisez <methodname>_getParam($key)</methodname> ou
- <methodname>_getAllParams()</methodname>. Vous pouvez aussi régler ces
- paramètres en utilisant <methodname>_setParam()</methodname> ;
- ceci est pratique quand vous redirigez vers des actions additionnelles.
- </para>
- <para>
- Pour tester si un paramètre existe ou non (pratique pour les branchements
- logiques), utilisez <methodname>_hasParam($key)</methodname>.
- </para>
- <note>
- <para>
- <methodname>_getParam()</methodname> peut prendre un second paramètre
- optionnel contenant une valeur par défaut à utiliser si le paramètre n'est
- pas réglé ou qu'il est vide. Utiliser ceci élimine la nécessité d'appeler
- <methodname>_hasParam()</methodname> avant de récupérer une valeur :
- </para>
- <programlisting language="php"><![CDATA[
- // Utilise une valeur par défaut de 1 si id n'est pas réglé
- $id = $this->_getParam('id', 1);
- // Au lieu de :
- if ($this->_hasParam('id') {
- $id = $this->_getParam('id');
- } else {
- $id = 1;
- }
- ]]></programlisting>
- </note>
- </listitem>
- </itemizedlist>
- </sect2>
- <sect2 id="zend.controller.action.viewintegration">
- <title>Intégration des Vues</title>
- <note id="zend.controller.action.viewintegration.viewrenderer">
- <title>
- Par défaut, l'intégration des vues est réalisé via le ViewRenderer
- </title>
- <para>
- Le contenu de cette section n'est valable que si vous avez explicitement
- désactivé le
- <link linkend="zend.controller.actionhelpers.viewrenderer">ViewRenderer</link>.
- Sinon, vous pouvez passer à la section suivante.
- </para>
- </note>
- <para>
- <classname>Zend_Controller_Action</classname> fournit un mécanisme rudimentaire
- et flexible pour l'intégration des vues. Deux méthodes accomplissent ceci,
- <methodname>initView()</methodname> et <methodname>render()</methodname> ; la
- première méthode charge la propriété publique <varname>$view</varname>, et la dernière
- effectue le rendu d'une vue basé sur l'action courante demandée dans la requête, en
- utilisant la hiérarchie des répertoires pour déterminer le chemin du script.
- </para>
- <sect3 id="zend.controller.action.viewintegration.initview">
- <title>Initialisation des Vues</title>
- <para>
- <methodname>initView()</methodname> initialise l'objet Vue.
- <methodname>render()</methodname> appelle <methodname>initView()</methodname> dans
- le but de récupérer l'objet de vue, mais il peut être
- initialisé à tout moment ; par défaut il remplit la propriété
- <varname>$view</varname> avec un objet <classname>Zend_View</classname>, mais toute
- classe implémentant <classname>Zend_View_Interface</classname> peut être utilisée.
- Si <varname>$view</varname> est déjà initialisé, il retourne simplement cette
- propriété.
- </para>
- <para>
- La mise en oeuvre par défaut suppose la structure de répertoire suivante :
- </para>
- <programlisting language="php"><![CDATA[
- applicationOrModule/
- controllers/
- IndexController.php
- views/
- scripts/
- index/
- index.phtml
- helpers/
- filters/
- ]]></programlisting>
- <para>
- En d'autres termes, les scripts de vues sont supposés être dans le
- sous-répertoire <filename>/views/scripts/</filename>, et le sous-répertoire
- <filename>/views/</filename> est censé contenir les fonctionnalités soeurs
- (aides [helpers], filtres [filters]). En déterminant le script de vue et son
- chemin, le répertoire <filename>/views/scripts/</filename> est utilisé comme
- chemin de base, avec des dossiers nommés par le nom de contrôleur fournissant
- ainsi la hiérarchie des scripts de vues.
- </para>
- </sect3>
- <sect3 id="zend.controller.action.viewintegration.render">
- <title>Effectuer le rendu des Vues</title>
- <para><methodname>render()</methodname> a la signature suivante :</para>
- <programlisting language="php"><![CDATA[
- string render(string $action = null,
- string $name = null,
- bool $noController = false);
- ]]></programlisting>
- <para>
- <methodname>render()</methodname> effectue le rendu d'un script de vue. Si aucun
- argument n'est fourni, la méthode suppose que le script requêté est
- <filename>[controller]/[action].phtml</filename> (où <filename>.phtml</filename>
- est la valeur de la propriété <varname>$viewSuffix</varname>). Fournir une valeur
- pour <varname>$action</varname> va effectuer le rendu du script dans le sous-dossier
- <filename>/[controller]/</filename>. Pour surcharger l'utilisation du sous-dossier
- <filename>/[controller]/</filename>, fournissez la valeur <constant>TRUE</constant>
- à <varname>$noController</varname>. Enfin, les scripts sont rendus dans l'objet
- réponse ; si vous souhaitez effectuer le rendu dans un
- <link linkend="zend.controller.response.namedsegments">segment
- nommé</link>spécifique de l'objet réponse, fournissez une valeur à
- <varname>$name</varname>.
- </para>
- <note>
- <para>
- Puisque le contrôleur et des noms d'action peuvent contenir des caractères
- délimiteurs de mot comme '_', '.' et '-', <methodname>render()</methodname>
- normalise ceux-ci à '-' en déterminant le nom du script. En interne, il utilise
- le délimiteur de mot et de chemin du istributeur pour faire cette normalisation.
- Ainsi, une requête pour <filename>/foo.bar/baz-bat</filename> rendra le
- script <filename>foo-bar/baz-bat.phtml</filename>. Si votre méthode d'action
- contient des notationsCamel, veuillez vous souvenir que ceci va résulter avec
- des mots séparés par '-' en déterminant le nom de fichier du script de vue.
- </para>
- </note>
- <para>Quelques exemples :</para>
- <programlisting language="php"><![CDATA[
- class MonController extends Zend_Controller_Action
- {
- public function fooAction()
- {
- // Effectue le rendu de mon/foo.phtml
- $this->render();
- // Effectue le rendu de mon/bar.phtml
- $this->render('bar');
- // Effectue le rendu de baz.phtml
- $this->render('baz', null, true);
- // Effectue le rendu de mon/login.phtml vers le segment
- // 'form' de l'objet réponse
- $this->render('login', 'form');
- // Effectue le rendu de site.phtml vers le segment
- // 'page' de l'objet réponse ; sans utiliser
- // le sous-dossier 'mon/'
- $this->render('site', 'page', true);
- }
- public function bazBatAction()
- {
- // Effectue le rendu de mon/baz-bat.phtml
- $this->render();
- }
- }
- ]]></programlisting>
- </sect3>
- </sect2>
- <sect2 id="zend.controller.action.utilmethods">
- <title>Méthodes utiles</title>
- <para>
- En plus de l'accesseur et des méthodes d'intégration de vue,
- <classname>Zend_Controller_Action</classname> possède plusieurs méthodes utiles pour
- exécuter des tâches communes de l'intérieur de vos méthodes d'action (ou de
- pre- / post-dispatch).
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <methodname>_forward($action, $controller = null, $module = null, array $params
- = null)</methodname> : exécute une autre action. Si appelé dans
- <methodname>preDispatch()</methodname>, la requête courante est évitée en
- faveur de la nouvelle. Sinon, après que l'action courante ait été exécutée,
- l'action demandée dans <methodname>_forward()</methodname> sera exécutée à
- son tour.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>_redirect($url, array $options = array())</methodname> :
- redirige vers une autre page. Cette méthode prend un <acronym>URL</acronym>
- et un jeu d'options optionnel. Par défaut, il exécute une redirection de
- type <acronym>HTTP</acronym> 302.
- </para>
- <para>Les options peuvent inclure une ou plusieurs des clés suivantes :</para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis></emphasis> : avec ou sans sortie immédiate. Si
- appelée, la méthode fermera proprement toute session ouverte et
- réalisera la redirection.
- </para>
- <para>
- Vous pouvez régler cette option de manière globale dans le
- contrôleur en utilisant l'accesseur
- <methodname>setRedirectExit()</methodname>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>prependBase</emphasis> : ajoute ou non
- l'<acronym>URL</acronym> de base enregistré dans l'objet
- requête à l'<acronym>URL</acronym> produit.
- </para>
- <para>
- Vous pouvez régler cette option de manière globale dans le
- contrôleur en utilisant l'accesseur
- <methodname>setRedirectPrependBase()</methodname>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>code</emphasis> : fournit le code <acronym>HTTP</acronym>
- à utiliser pour la redirection. Par défaut, un <acronym>HTTP</acronym>
- 302 est utilisé ; tout code compris entre 301 et 306 peut être utilisé.
- </para>
- <para>
- Vous pouvez régler cette option de manière globale dans le
- contrôleur en utilisant l'accesseur
- <methodname>setRedirectCode()</methodname>.
- </para>
- </listitem>
- </itemizedlist>
- </listitem>
- </itemizedlist>
- </sect2>
- <sect2 id="zend.controller.action.subclassing">
- <title>Sous-classer le contrôleur d'action</title>
- <para>
- Par conception, <classname>Zend_Controller_Action</classname> doit être
- sous-classé pour créer un contrôleur d'action. Au minimum, vous devez définir les
- méthodes d'action que le contrôleur d'action peut appeler.
- </para>
- <para>
- En plus de la création de fonctionnalité utile pour vos applications Web, vous
- pouvez aussi constater que vous répétez souvent la même installation ou les mêmes
- méthodes utilitaires dans vos contrôleurs divers ; s'il en est ainsi, créer une classe
- de contrôleur de base commune qui étend <classname>Zend_Controller_Action</classname>
- peut résoudre une telle redondance.
- </para>
- <example id="zend.controller.action.subclassing.example-call">
- <title>Comment gérer des actions non-existantes</title>
- <para>
- Si une requête vers un contrôleur est faite en incluant une méthode d'action
- indéfinie, <methodname>Zend_Controller_Action::__call()</methodname> sera invoqué.
- <methodname>__call()</methodname> est, bien sûr, la méthode magique de
- <acronym>PHP</acronym> pour la surcharge de méthode.
- </para>
- <para>
- Par défaut, cette méthode lève une
- <classname>Zend_Controller_Action_Exception</classname> indiquant que la méthode
- requêtée n'a pas été trouvée dans le contrôleur. Si la méthode requêtée se termine
- par "Action", on considère qu'une action était requêté et qu'elle n'existe pas ; un
- telle erreur entraîne une exception ayant un code 404. Tout autre appel de méthode
- entraîne une exception ayant un code 500. Ceci vous permet de facilement
- différencier une page inconnue et une erreur de l'application dans votre
- gestionnaire d'erreur.
- </para>
- <para>
- Vous pouvez surcharger cette fonctionnalité si vous souhaitez exécuter
- d'autres opérations. Par exemple, si vous souhaitez afficher un message d'erreur,
- vous pouvez écrire quelque chose comme ceci :
- </para>
- <programlisting language="php"><![CDATA[
- class MonController extends Zend_Controller_Action
- {
- public function __call($method, $args)
- {
- if ('Action' == substr($method, -6)) {
- // Si une méthode d'action n'est pas trouvée,
- // rendre le script d'erreur
- return $this->render('error');
- }
- // pour toute autre méthode, levée d'une exception
- throw new Exception('Méthode invalide "' . $method . '" appelée',
- 500);
- }
- }
- ]]></programlisting>
- <para>
- Une autre possibilité est de rediriger vers une page de contrôleur par
- défaut :
- </para>
- <programlisting language="php"><![CDATA[
- class MyController extends Zend_Controller_Action
- {
- public function indexAction()
- {
- $this->render();
- }
- public function __call($method, $args)
- {
- if ('Action' == substr($method, -6)) {
- // Si une méthode d'action n'est pas trouvée,
- // rediriger vers l'action index
- return $this->_forward('index');
- }
- // pour tout autre méthode, levée d'une exception
- throw new Exception('Méthode invalide "' . $method . '" appelée',
- 500);
- }
- }
- ]]></programlisting>
- </example>
- <para>
- En plus de la surcharge de <methodname>__call()</methodname>, chacune des méthodes
- d'initialisation , utilitaires, d'accesseurs, de vues et de détournement de la
- distribution mentionnées ci-dessus peuvent être surchargées dans le but de
- personnaliser vos contrôleurs. Par exemple, si vous stockez votre objet de vue dans le
- registre, vous pouvez vouloir modifier votre méthode <methodname>initView()</methodname>
- avec une code comme celui-ci :
- </para>
- <programlisting language="php"><![CDATA[
- abstract class Ma_Base_Controller extends Zend_Controller_Action
- {
- public function initView()
- {
- if (null === $this->view) {
- if (Zend_Registry::isRegistered('view')) {
- $this->view = Zend_Registry::get('view');
- } else {
- $this->view = new Zend_View();
- $this->view->setBasePath(dirname(__FILE__) . '/../views');
- }
- }
- return $this->view;
- }
- }
- ]]></programlisting>
- <para>
- En espérant que les informations de ce chapitre vous permettent de voir la
- flexibilité de ce composant particulier et comment vous pouvez le modifier suivant les
- besoins de votre application.
- </para>
- </sect2>
- </sect1>
|