# Plugins

## Introduction

L'architecture MVC de Zend Framework propose l'injection de plugins de code, qui vont intervenir à différents niveaux dans le processus complet. Le contrôleur frontal enregistre des plugins, et utilise un gestionnaire de plugins ("plugin broker"), qui va se charger de faire intervenir chaque plugin, à chacun des instants clés à votre disposition.

Les instants clés sont des méthodes événementielles définies dans la classe abstraite `Zend_Controller_Plugin_Abstract`, dont tous les plugins doivent hériter :

- `routeStartup()` est appelée avant que `Zend_Controller_Front` n'appelle le routeur pour évaluer ses routes et remplir la requête.

- `routeShutdown()` est appelée après que le routeur aie fini de router la requête.

- `dispatchLoopStartup()` est appelée juste avant que `Zend_Controller_Front` n'entre en boucle de distribution.

- `preDispatch()` est appelée avant qu'une action ne soit distribuée par le distributeur. Cette méthode permet un filtrage ou un proxy. En jouant sur la requête à ce niveau là, vous êtes capable de changer le processus, et en vous aidant de `Zend_Controller_Request_Abstract::setDispatched(true)`), vous supprimez l'ordre de distribution de celle-ci.

- `postDispatch()` est appelée après qu'une action n'ait été distribuée par le distributeur. Cette méthode permet un filtrage ou un proxy. En jouant sur la requête à ce niveau là, vous êtes capable de changer le processus, et en vous aidant de `Zend_Controller_Request_Abstract::setDispatched(false)`), vous ordonnez une redistribution de celle-ci.

- `dispatchLoopShutdown()` est appelée par `Zend_Controller_Front` lorsque celui-ci sort de la boucle de distribution.

## Écrire des plugins

Tous les plugins doivent hériter de `Zend_Controller_Plugin_Abstract`:

    class MyPlugin extends Zend_Controller_Plugin_Abstract
    {
        // ...
    }

Comme aucune des méthodes de `Zend_Controller_Plugin_Abstract` n'est abstraite, vous n'êtes pas obligé dans vos plugins de toutes les définir. Vous agissez aux endroits que vous voulez.

`Zend_Controller_Plugin_Abstract` vous donne aussi accès aux objets de réponse et de requête, dans vos plugins.`getRequest()` et `getResponse()` sont là pour ça. Cependant, l'objet de requête est de toute façon passé en paramètre à vos méthodes. Veillez à le récupérer dans la définition de vos méthodes sinon une erreur `E_STRICT` sera levée.

## Utilisation des plugins

Les plugins sont enregistrés avec `Zend_Controller_Front::registerPlugin()`, et peuvent l'être n'importe quand. Voici un exemple :

    class MyPlugin extends Zend_Controller_Plugin_Abstract
    {
        public function routeStartup(
                    Zend_Controller_Request_Abstract $request)
        {
            $this->getResponse()
                 ->appendBody("<p>routeStartup() appelée</p>\n");
        }

        public function routeShutdown(
                    Zend_Controller_Request_Abstract $request)
        {
            $this->getResponse()
                 ->appendBody("<p>routeShutdown() appelée</p>\n");
        }

        public function dispatchLoopStartup(
                    Zend_Controller_Request_Abstract $request)
        {
            $this->getResponse()
                 ->appendBody("<p>dispatchLoopStartup() appelée</p>\n");
        }

        public function preDispatch(
                    Zend_Controller_Request_Abstract $request)
        {
            $this->getResponse()
                 ->appendBody("<p>preDispatch() appelée</p>\n");
        }

        public function postDispatch(
                    Zend_Controller_Request_Abstract $request)
        {
            $this->getResponse()
                 ->appendBody("<p>postDispatch() appelée</p>\n");
        }

        public function dispatchLoopShutdown()
        {
            $this->getResponse()
                 ->appendBody("<p>dispatchLoopShutdown() appelée</p>\n");
        }
    }

    $front = Zend_Controller_Front::getInstance();
    $front->setControllerDirectory('/path/to/controllers')
          ->setRouter(new Zend_Controller_Router_Rewrite())
          ->registerPlugin(new MyPlugin());
    $front->dispatch();

Si aucune autre action ne génère une sortie (typiquement, un rendu de vue), alors le résultat suivant devrait s'afficher :

    <p>routeStartup() appelée</p>

    <p>routeShutdown() appelée</p>

    <p>dispatchLoopStartup() appelée</p>

    <p>preDispatch() appelée</p>

    <p>postDispatch() appelée</p>

    <p>dispatchLoopShutdown() appelée</p>

Enregistrez vos plugins où vous voulez dans votre code, mais faites attention de ne pas leur faire sauter de méthodes, selon l'endroit où vous les enregistrez.

## Récupération et manipulations des plugins

Il peut arriver que vous ayez besoin de récupérer des plugins, ou d'en supprimer. Les méthodes suivantes vous seront alors utiles :

- `getPlugin($class)` vous retourne l'objet de plugin correspondant à la chaîne passée en paramètre. Si il n'y a pas de correspondance, `FALSE` est retourné. Un tableau est retourné s'il y a plusieurs plugins de cette classe.

- `getPlugins()` retourne toute la pile de plugins.

- `unregisterPlugin($plugin)` supprime un plugin du processus. Passez un nom de classe, et tous les plugins de cette classe seront alors enlevés de la pile. Vous pouvez aussi passer un objet.

## Plugins inclus dans Zend Framework

Zend Framework possède des plugins dans sa distribution :