Previous Next

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 quele routeur aie fini de router la requête.

  • dispatchLoopStartup() est appelée juste avant que Zend_Controller_Front n'entre en boucle de dispatching.

  • preDispatch() est appelée avant qu'une action ne soit dispatchée par le dispatcheur. 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 dispatching de celle-ci.

  • postDispatch() est appelée après qu'une action n'ait été dispatchée par le dispatcheur. 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 un redispatching de celle-ci.

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

É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("

routeStartup() appelée

\n"); } public function routeShutdown( Zend_Controller_Request_Abstract $request) { $this->getResponse() ->appendBody("

routeShutdown() appelée

\n"); } public function dispatchLoopStartup( Zend_Controller_Request_Abstract $request) { $this->getResponse() ->appendBody("

dispatchLoopStartup() appelée

\n"); } public function preDispatch( Zend_Controller_Request_Abstract $request) { $this->getResponse() ->appendBody("

preDispatch() appelée

\n"); } public function postDispatch( Zend_Controller_Request_Abstract $request) { $this->getResponse() ->appendBody("

postDispatch() appelée

\n"); } public function dispatchLoopShutdown() { $this->getResponse() ->appendBody("

dispatchLoopShutdown() appelée

\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 :

routeStartup() appelée

routeShutdown() appelée

dispatchLoopStartup() appelée

preDispatch() appelée

postDispatch() appelée

dispatchLoopShutdown() appelée

Note:

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é si 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 :

ActionStack

Le plugin ActionStack vous permet de gérer une pile de requêtes en opérant en postDispatch. Si un forward (un appel à une autre action) est détecté, alors le plugin n'agira pas. Dans le cas contraire cependant, sa pile est analysée (en ordre LIFO : dernier empilé, premier dépilé) et une nouvelle action est dispatchée. Ce plugin est commandé par l'aide d'action du même nom ActionStack

Vous pouvez récupérer ce plugin grâce à Zend_Controller_Front::getPlugin('Zend_Controller_Plugin_ActionStack'). Une fois l'objet retourné, voici les méthodes qui y sont proposées :

  • getRegistry() et setRegistry(). En interne, ActionStack utilise Zend_Registry pour stocker sa pile. Vous pouvez manipuler l'instance du registre utilisée grâce à ces méthodes.

  • getRegistryKey() et setRegistryKey(). Ces méthodes vous donnent accès à la clé utilisée dans le registre, pour stocker la pile d'actions de ActionStack. Par défaut, il s'agit de Zend_Controller_Plugin_ActionStack.

  • getStack() retourne la pile (entière) d'actions.

  • pushStack() et popStack() contrôlent la pile. popStack() supprime l'action la plus haute dans la pile (l'action à venir), et vous la retourne. pushStack() rajoute une action sur la pile. Vous devez la passer en paramètre donc.

La méthode forward(), elle, est directe : elle attend un objet de requête qu'elle passe immédiatement au contrôleur frontal en redemandant un jeton de dispatching.

Zend_Controller_Plugin_ErrorHandler

Zend_Controller_Plugin_ErrorHandler est un plugin intégré d'office dans le modèle MVC, il sert à gérer les exceptions envoyées par l'application, en particulier celles concernant des contrôleurs ou des actions manquants. C'est une manière rejoignant la section Exceptions MVC.

Les principaux objectifs de ce plugin sont :

  • Intercepter les exceptions envoyées si un contrôleur ou une action ne peuvent être trouvés

  • Intercepte les exceptions envoyées dans les contrôleurs

Globalement, ErrorHandler sert à gérer les erreurs 404 ou 500. Attention, le plugin n'est pas destiné à intervenir sur les exceptions envoyées dans d'autres plugins. Des effets de bords peuvent apparaître, veillez à les gérer.

Par défaut, Zend_Controller_Plugin_ErrorHandler redirige vers ErrorController::errorAction() dans le module par défaut. Vous pouvez passer d'autres valeurs via les accesseurs du plugin :

  • setErrorHandlerModule() définit le module à utiliser.

  • setErrorHandlerController() définit le contrôleur à utiliser.

  • setErrorHandlerAction() définit l'action à utiliser.

  • setErrorHandler() est un raccourci des trois précédantes. Passez un tableau avec les clés "module", "controller", or "action", et leurs valeurs appropriées.

Ce comportement fonctionne aussi avec le constructeur du plugin. Celui-ci agit comme un proxy vers setErrorHandler().

Zend_Controller_Plugin_ErrorHandler agit en postDispatch() et analyse l'objet de réponse à la recherche d'éventuelles exceptions. Si il y en a, alors le plugin modifie la requête pour dispatcher le contrôleur et l'action d'erreur.

Si une exception arrive lorsque le plugin agit, alors celui-ci ordonne au contrôleur frontal de renvoyer l'exception. C'est pour cela qu'il faudrait systématiquement entourer sa méthode dispatch, du contrôleur frontal; d'un bloc try / catch.

Utilisation de ErrorHandler pour gérer les erreurs 404

Comme ErrorHandler capture les exceptions relatives à un problème de contrôleur ou action manquants, vous pouvez donc l'utiliser comme un gestionnaire d'erreurs 404. Pour cela, il faut analyser le type d'exception ayant mené à l'erreur.

Les exceptions capturées sont enregistrées en tant que paramètre d'action. Zend_Controller_Action::_getParam('error_handler'):

class ErrorController extends Zend_Controller_Action
{
    public function errorAction()
    {
        $errors = $this->_getParam('error_handler');
    }
}

Une fois que vous possédez l'objet contenant l'exception, inspectez son type avec $errors->type. Des constantes sont à votre disposition:

  • Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER, indique un contrôleur non trouvé.

  • Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION, indique qu'une action est absente.

  • Zend_Controller_Plugin_ErrorHandler::EXCEPTION_OTHER, indique une autre exception.

Les deux premiers types pourraient mener à une erreur 404 :

class ErrorController extends Zend_Controller_Action
{
    public function errorAction()
    {
        $errors = $this->_getParam('error_handler');

        switch ($errors->type) {
            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
                // erreur 404 -- contrôleur ou action introuvable
                $this->getResponse()->setRawHeader('HTTP/1.1 404 Not Found');

                // ... ici, de l'affichage (du rendu)
                break;
            default:
                // erreur applicative; affiche une page d'erreur, mais sans changer le code de
                // retour HTTP
                break;
        }
    }
}

Enfin, il est possible de récupérer l'exception ayant menée au contrôleur d'erreur. Ceci afin de l'analyser. L'attribut exception de l'objet le permet :

public function errorAction()
{
        $errors = $this->_getParam('error_handler');


        switch ($errors->type) {
            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
                // erreur 404 -- contrôleur ou action introuvable
                $this->getResponse()->setRawHeader('HTTP/1.1 404 Not Found');

                // ... ici, de l'affichage (du rendu)
                break;
            default:
                // erreur applicative; affiche une page d'erreur,
                // mais sans changer le code de retour HTTP

                // ...

                // Sauve l'exception en log:
                $exception = $errors->exception;
                $log =
                    new Zend_Log(
                        new Zend_Log_Writer_Stream(
                            '/tmp/applicationException.log')
                    );
                $log->debug($exception->getMessage()
                          . "\n"
                          . $exception->getTraceAsString());
                break;
        }
}

Gestion des rendus précédants de la réponse

Si vous décomposez vos processus en plusieurs actions ou plusieurs appels à render(), il est possible que la réponse contienne déjà des éléments lorsque ErrorHandler agit.

Si vous désirez rendre votre contrôleur d'erreur dans ce contenu, alors il n'y a rien à faire de spécial. En revanche, il peut aussi être judicieux de vider totalement la réponse afin de rendre le contrôleur d'erreurs. Procédez alors comme suit:

$this->getResponse()->clearBody();

Exemples d'utilisation

Example #1 Utilisation standard et désactivation

$front = Zend_Controller_Front::getInstance();
$front->registerPlugin(new Zend_Controller_Plugin_ErrorHandler());

Notez bien que l'exemple ci-dessus ne sert pas à grand chose : le plugin ErrorHandler est actif par défaut, dans le contrôleur frontal. Il est cependant possible de le désactiver, passez un paramètre au contrôleur frontal :

$front = Zend_Controller_Front::getInstance();
$front->setParam('noErrorHandler',true);

Example #2 Paramétrage du plugin

$front = Zend_Controller_Front::getInstance();
$front->registerPlugin(new Zend_Controller_Plugin_ErrorHandler(array(
    'module'     => 'mystuff',
    'controller' => 'static',
    'action'     => 'error'
)));

Example #3 Utilisation des accesseurs

$plugin = new Zend_Controller_Plugin_ErrorHandler();
$plugin->setErrorHandlerModule('mystuff')
       ->setErrorHandlerController('static')
       ->setErrorHandlerAction('error');

$front = Zend_Controller_Front::getInstance();
$front->registerPlugin($plugin);

Exemple de contrôleur d'erreurs

Pour utiliser le plugin ErrorHandler, un contrôleur d'erreurs est requis. En voici un exemple :

class ErrorController extends Zend_Controller_Action
{
    public function errorAction()
    {
        $errors = $this->_getParam('error_handler');

        switch ($errors->type) {
            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
                // erreur 404 -- contrôleur ou action non trouvé
                $this->getResponse()->setRawHeader('HTTP/1.1 404 Not Found');

                $content =<<Erreur!

Page introuvable.

EOH; break; default: // erreur d'application $content =<<Erreur!

Une erreur innatendue est survenue

EOH; break; } // Vide la réponse $this->getResponse()->clearBody(); $this->view->content = $content; } }
Previous Next
Introduction to Zend Framework
Présentation
Installation
Zend_Acl
Introduction
Affiner les Contrôles d'Accès
Utilisation avancée
Zend_Amf
Introduction
Zend_Amf_Server
Zend_Auth
Introduction
Authentification avec une table de base de données
Authentification "Digest"
Adaptateur d'authentification HTTP
LDAP Authentication
Authentification OpenID
Zend_Cache
Introduction
Aspect théorique
Les frontends Zend_Cache
Les backends Zend_Cache
Zend_Captcha
Introduction
Opération Captcha
Adaptateurs Captcha
Zend_Config
Introduction
Aspect théorique
Zend_Config_Ini
Zend_Config_Xml
Zend_Config_Writer
Zend_Config_Writer
Zend_Console_Getopt
Introduction à Getopt
Déclarer les règles Getopt
Extraire les options et les arguments
Configurer Zend_Console_Getopt
Zend_Controller
Zend_Controller - Démarrage rapide
Fondations de Zend_Controller
Le contrôleur frontal (Front Controller)
L'objet Requête
Routeur Standard
Le dispatcheur
Contrôleurs d'action
Aides d'action (Helper)
Objet de réponse
Plugins
Utilisation de conventions de dossiers modulaires
Exceptions avec MVC
Migrer depuis des versions précédentes
Zend_Currency
Introduction à Zend_Currency
How to work with currencies
Migrer depuis des versions antérieures
Zend_Date
Introduction
Aspect théorique
Méthodes de base
Zend_Date API Overview
Créer des dates
Constants for General Date Functions
Exemples concrets
Zend_Db
Zend_Db_Adapter
Zend_Db_Statement
Zend_Db_Profiler
Zend_Db_Select
Zend_Db_Table
Zend_Db_Table_Row
Zend_Db_Table_Rowset
Relations Zend_Db_Table
Zend_Debug
Afficher des informations
Zend_Dojo
Introduction
Zend_Dojo_Data: dojo.data Envelopes
Les aides de vues Dojo
Les éléments de formulaire et les décorateurs Dojo
Zend_Dom
Introduction
Zend_Dom_Query
Zend_Exception
Utiliser les exceptions
Zend_Feed
Introduction
Importer des flux
Obtenir des flux à partir de pages Web
Consommer un flux RSS
Consommer un flux Atom
Consommer une entrée Atom particulière
Modifier la structure du flux ou des entrées
Classes personnalisées pour les flux et entrées
Zend_File
Zend_File_Transfer
Validateurs pour Zend_File_Transfer
Filtres pour Zend_File_Transfer
Migrer à partir des versions précédentes
Zend_Filter
Introduction
Classes de filtre standards
Chaînes de filtrage
Écriture de filtres
Zend_Filter_Input
Zend_Filter_Inflector
Zend_Form
Zend_Form
Zend_Form Quick Start
Creating Form Elements Using Zend_Form_Element
Creating Forms Using Zend_Form
Creating Custom Form Markup Using Zend_Form_Decorator
Standard Form Elements Shipped With Zend Framework
Standard Form Decorators Shipped With Zend Framework
Internationalization of Zend_Form
Advanced Zend_Form Usage
Zend_Gdata
Introduction to Gdata
Authentification par procédé AuthSub
Using the Book Search Data API
Authentification avec ClientLogin
Using Google Calendar
Using Google Documents List Data API
Using Google Health
Using Google Spreadsheets
Using Google Apps Provisioning
Using Google Base
Utilisation des albums Web Picasa
Using the YouTube Data API
Attraper les exceptions Gdata
Zend_Http
Zend_Http_Client - Introduction
Zend_Http_Client - Utilisation avancée
Zend_Http_Client - Adaptateurs de connexion
Zend_Http_Cookie and Zend_Http_CookieJar
Zend_Http_Response
Zend_InfoCard
Introduction
Zend_Json
Introduction
Utilisation de base
Objets JSON
XML to JSON conversion
Zend_Json_Server - JSON-RPC server
Zend_Layout
Introduction
Zend_Layout - Démarrage rapide
Zend_Layout options de configuration
Zend_Layout, utilisation avancée
Zend_Ldap
Introduction
Zend_Loader
Charger les fichiers et les classes dynamiquement
Chargeur de Plugins
Zend_Locale
Introduction
Using Zend_Locale
Normalization and Localization
Working with Dates and Times
Supported locales
Migrer à partir des versions précédentes
Zend_Log
Présentation
Rédacteurs (Writers)
Formateurs (mise en forme)
Filtres
Zend_Mail
Introduction
Envoyer des émail en utilisant SMTP
Envoyer plusieurs émail par connexion SMTP
Utiliser différents transports
Émail HTML
Fichiers joints
Ajouter des destinataires
Contrôler les limites MIME
Entêtes additionnelles
Jeux de caractères
Encodage
Authentification SMTP
Sécuriser les transports SMTP
Lire des émail
Zend_Measure
Introduction
Création d'une mesure
Récupérer des mesures
Manipuler des mesures
Types de mesures
Zend_Memory
Présentation
Manager de mémoire
Objet mémoire
Zend_Mime
Zend_Mime
Zend_Mime_Message
Zend_Mime_Part
Zend_OpenId
Introduction
Zend_OpenId_Consumer Basics
Zend_OpenId_Provider
Zend_Paginator
Introduction
Utilisation
Configuration
Utilisation avancée
Zend_Pdf
Introduction.
Créer et charger des documents PDF
Sauvegarder les changement dans un document PDF
Les pages d'un document
Dessiner
Informations du document et métadonnées.
Exemple d'utilisation du module Zend_Pdf
Zend_ProgressBar
Zend_ProgressBar
Zend_Registry
Utiliser le registre
Zend_Rest
Introduction
Zend_Rest_Client
Zend_Rest_Server
Zend_Search_Lucene
Overview
Building Indexes
Searching an Index
Query Language
Query Construction API
Jeu de caractères
Extensibility
Agir avec Lucene Java
Avancé
Best Practices
Zend_Server
Introduction
Zend_Server_Reflection
Zend_Service
Introduction
Zend_Service_Akismet
Zend_Service_Amazon
Zend_Service_Audioscrobbler
Zend_Service_Delicious
Zend_Service_Flickr
Zend_Service_Nirvanix
Zend_Service_ReCaptcha
Zend_Service_Simpy
Introduction
Zend_Service_StrikeIron
Zend_Service_StrikeIron: Bundled Services
Zend_Service_StrikeIron: Advanced Uses
Zend_Service_Technorati
Zend_Service_Twitter
Zend_Service_Yahoo
Zend_Session
Introduction
Usage basique
Utilisation avancée
Gestion générale de la session
Zend_Session_SaveHandler_DbTable
Zend_Soap
Zend_Soap_Server
Zend_Soap_Client
WSDL
Auto découverte
Zend_Test
Introduction
Zend_Test_PHPUnit
Zend_Text
Zend_Text_Figlet
Zend_Text_Table
Zend_TimeSync
Introduction
Utiliser Zend_TimeSync
Zend_Translate
Introduction
Adaptateurs pour Zend_Translate
Utiliser les adaptateurs de traduction
Migrer à partir des versions précédentes
Zend_Uri
Zend_Uri
Zend_Validate
Introduction
Classes de validation standard
Chaînes de validation
Écrire des validateurs
Zend_Version
Lire la version du Zend Framework
Zend_View
Introduction
Scripts de contrôleur
Scripts de vue
Aides de vue
Zend_View_Abstract
Zend_Wildfire
Zend_Wildfire
Zend_XmlRpc
Introduction
Zend_XmlRpc_Client
Zend_XmlRpc_Server
Configuration système requise par le Zend Framework
Version de PHP requise
Extensions PHP
Les composants du Zend Framework
Dépendances internes du Zend Framework
Convention de codage PHP du Zend Framework
Vue d'ensemble
Formatage des fichiers PHP
Conventions de nommage
Style de codage
Zend Framework Performance Guide
Introduction
Class Loading
Internationalisation (i18n) and Localisation (l10n)
View Rendering
Informations de copyright