7.3. Sous-classement
Précédent | Chapitre 7. Zend_Controller | Suivant

## 7.3. Sous-classement

### 7.3.1. Introduction

Le `Zend_Controller` a été pensé dans un soucis permanent d'extensibilité, soit en faisant des sous-classes des classes existantes, soit en écrivant de nouvelles classes qui implémentent les interfaces `Zend_Controller_Router_Interface` et `Zend_Controller_Dispatcher_Interface`.

Les raisons possibles pour implémenter un nouveau routeur ou un nouvel aiguilleur peuvent être :

- Le système existant de routage d'URI ne convient pas, par exemple lors de son intégration dans un site Web existant qui utilise déjà ses propres conventions de routage, qui ne s'accordent pas avec les mécanisme de routage fournis par le Framework Zend.

- Vous avez besoin d'implémenter un routage pour quelque chose de complètement différent. La classe `Zend_Controller_Router` ne fonctionne qu'avec des URIs. Il est possible et préférable que vous vouliez utiliser le design pattern MVC pour développer un autre type de programme, comme une application en console. Dans le cas d'une application en console, un routeur personnalisé devrait traiter les arguments de la ligne de commande pour définir la route.

- Le mécanisme fournit par le `Zend_Controller_Dispatcher` n'est pas approprié. La configuration par défaut suppose par convention que les contrôleurs sont des classes et les action, des méthodes de ces classes. Cependant, il existe beaucoup d'autres statégies pour le faire. Un exemple serait de faire correspondre un contrôleur à un répertoire, et les actions de ce contrôleur aux fichiers à l'intérieur de ces répertoires, au lieu d'appeller une méthode d'une classe, ceci pourrait permettre d'inclure un fichier d'un répertoire.

- Vous souhaitez fournir des possibilités aditionnelles qui seront héritées par tous vos contrôleurs. Par exemple `Zend_Controller_Action` n'intègre pas `Zend_View` par défaut. Cependant, vous pourriez étendre votre propre contrôleur pour faire cela, et l'utiliser ne nécessiterait pas de modifier ni `Zend_Controller_Router` ni `Zend_Controller_Dispatcher`.

Soyez attentifs lorsque vous surchargez une part importante du système, en particulier l'aiguilleur. Un des avantages de `Zend_Controller` est qu'il établit des conventions communes pour la création d'applications. Si trop de ces comportements par défaut sont modifiés, un certain nombre de ces avantages seront perdus. Cependant, il y a de nombreux besoins différents, et une seule solution ne peut y répondre complètement, d'où la liberté fournie si besoin est.

### 7.3.2. Conventions

Lors d'un sous-classement d'une des classes du Zend_Controlleur, il est fortement recommandé de suivre ces conventions pour nommer ou enregistrer les fichiers. Suivre cette méthode vous assure qu'un autre développeur familier avec le Framework Zend sera capable de comprendre facilement votre projet.

#### 7.3.2.1. Préfixage

Les classes inclues dans le Framework Zend suivent une convention ou chaque classe est préfixée par "`Zend_`". C'est le préfixe. Nous recommandons que toutes vos classes soient nommées de la même façon, c'est à dire si le nom de votre entreprise est Widget, Inc., le préfixe pourrait être "`Widget_`".

#### 7.3.2.2. Arborescence des répertoires

Les classes `Zend_Controller` sont stockées dans le répertoire library comme ceci :

    /library
      /Zend
        /Controller
          Action.php
          Dispatcher.php
          Router.php

En cas de sous-classement de `Zend_Controller` , il est recommandé que les nouvelles classes soient stockées dans une structure identique avec votre préfixe. Cela facilitera la recherche pour qui est chargé de relire le code de votre projet.

Par exemple, un projet de Widget, Inc. qui implémente uniquement un routeur personnalisé, l'arborescence ressemblerait à ceci :

    /library
      /Zend
      /Widget
        /Controller
          Router.php
          README.txt

Veuillez noter que dans cet exemple, le répertoire `Widget/Controller/` est la copie conforme du répertoire `Zend/Controller/` lorsque c'est possible. Dans le cas présent, il fournit la classe `Widget_Controller_Router`, qui serait soit une sous-classe, soit un remplacement de `Zend_Controller_Router` implémentant `Zend_Controller_Router_Interface`.

Veuillez noter aussi que dans l'exemple ci-dessus, un fichier `README.txt` a été placé dans `Widget/Controller/`. Zend vous encourage fortement à documenter vos projets en proposant des tests séparés, et une documentation pour vos clients. Cependant, nous vous conseillons aussi de placer un simple fichier `README.txt` directement dans le répertoire pour expliquer brièvement vos changements, et leurs fonctionnements.

### 7.3.3. Interface de Routage

L'interface `Zend_Controller_Router_Interface` fournie une définition pour une seule méthode :

    <?php

      /**
       * @param  Zend_Controller_Dispatcher_Interface
       * @throws Zend_Controller_Router_Exception
       * @return Zend_Controller_Dispatcher_Token|boolean
       */
      public function route(Zend_Controller_Dispatcher_Interface $dispatcher);

    ?>

Le routage n'a lieu qu'une seule fois : lorsque la requête est reçue en premier par le système. Le but de ce routeur est de générer un `Zend_Controller_Dispatch_Token` qui spécifie un contrôleur et une action qui lui est associée. Ceci est ensuite passé dans l'aiguilleur. S'il n'est pas possible de définir une route pour un jeton d'aiguillage (nonsenical route) alors un bouléen `FALSE` est retourné.

Certains routeurs peuvent traiter des éléments dynamiques et ont besoin d'un moyen pour déterminer si le jeton d'aiguillage généré est aiguillable avant de le retourner. Pour cette raison, le routeur reçoit un objet gestionnaire de l'aiguilleur comme unique argument de sa méthode `route()`. L'aiguilleur fournit une méthode de test `isDispatchable()`.

### 7.3.4. Interface d'aiguillage

`Zend_Controller_Front` appelera premièrement le routeur pour recevoir le premier jeton d'aiguillage, qu'il passera à l'aiguilleur. L'aiguilleur aiguillera l'action (instancier le contrôleur, appeler son action) et retournera ensuite soit un bouléen, FALSE, soit un autre jeton d'aiguillage.

`Zend_Controller_Front` apelle l'aiguilleur continuellement, jusqu'à ce qu'un jeton d'aiguillage ne lui soit pas retourné. Ceci s'apelle la boucle d'aiguillage. Elle permet aux actions d'être traitées séquentiellement jusqu'à ce que toutes les tâches soient effectuées.

L'interface `Zend_Controller_Dispatcher_Interface` fournie des définitions pour les deux méthodes suivantes :

    <?php

    /**
     * @param  Zend_Controller_Dispatcher_Token $route
     * @return boolean
     */
    public function isDispatchable(Zend_Controller_Dispatcher_Token $route);

    ?>

`isDispatchable()` vérifie si le jeton d'aiguillage est aiguillable. Si c'est le cas, elle retourne `TRUE`. Dans les autres cas, elle retourne `FALSE`. La définition de ce qui est aiguillable est laissée à la classe qui implémente l'interface. Dans le cas de l'implémentation par défaut `Zend_Controller_Dispatcher`, cela veut dire que le fichier contrôleur existe, la classe existe dans ce fichier, et que la méthode d'action existe dans cette classe.

    <?php

    /**
     * @param  Zend_Controller_Dispatcher_Token $route
     * @return Zend_Controller_Dispatcher_Token|boolean
     */
    public function dispatch(Zend_Controller_Dispatcher_Token $route);

    ?>

La méthode `dispatch()` constitue l'endroit où le vrai travail s'effectue. Cette méthode doit exécuter l'action du contrôleur. Elle doit aussi retourner un jeton d'aiguillage, ou un bouléen, FALSE, pour indiquer qu'il n'y a plus de tâches à effectuer.

Précédent | Niveau supérieur | Suivant
7.2. Mise en Route | Sommaire | 7.4. Provided Subclasses