Programmer's Reference Guide
Les aides d'action permettent aux développeurs d'injecter, en cours d'exécution et/ou à la demande, des
fonctionnalités dans tout contrôleur d'action qui étend Zend_Controller_Action. Le but des aides
d'action est de minimiser la nécessité d'étendre le contrôleur d'action abstrait en y injectant des
fonctionnalités communes de contrôleur d'action.
Il y a de nombreuses manières d'utiliser les aides d'action. Les aides d'action utilisent le système de
gestionnaire ("Broker"), similaire aux gestionnaires vus pour les Zend_View_Helper, et les Zend_Controller_Plugin. Les aides d'action (comme les aides de vue
Zend_View_Helper) peuvent être chargées et appelées à la demande, ou elles peuvent être instanciées
au début de la requête ("bootstrap") ou au moment de la création des contrôleurs d'action (init()).
Pour mieux comprendre ceci, reportez vous à la section d'utilisation ci-dessous.
Une aide peut être initialisée de plusieurs manières différentes, basées sur vos besoins aussi bien que la fonctionnalité de l'aide.
Le gestionnaire d'aide est stocké en tant que membre $_helper du
Zend_Controller_Action ; utilisez le gestionnaire pour récupérer ou appeler les aides. Les méthodes
pour faire ceci incluent :
-
L'utilisation explicite de
getHelper(). Passez lui simplement un nom, et l'objet d'aide est retourné :$flashMessenger = $this->_helper->getHelper('FlashMessenger');
$flashMessenger->addMessage('Nous avons fait quelquechose lors de la dernière requête'); -
L'utilisation de la fonctionnalité
__get()du gestionnaire d'aide et récupérez l'aide comme si elle était une propriété membre du gestionnaire :$flashMessenger = $this->_helper->FlashMessenger;
$flashMessenger->addMessage('Nous avons fait quelquechose lors de la dernière requête'); -
Enfin, la plupart des aides d'action implémente la méthode
direct()qui va appeler une méthode spécifique par défaut dans l'aide. Dans l'exemple deFlashMessenger, ceci appelleaddMessage():$this->_helper->FlashMessenger('Nous avons fait quelquechose lors de la dernière requête');
![]() |
Note |
|---|---|
Tous les exemples ci-dessus sont équivalents. |
Vous pouvez vouloir aussi instancier les aides explicitement. Vous pourriez avoir besoin de ceci si vous utilisez l'aide hors du contexte du contrôleur d'action, ou si vous souhaitez fournir une aide au gestionnaire d'aides à utiliser pour une action quelconque. L'instanciation se fait comme toute autre classe PHP.
Zend_Controller_Action_HelperBroker gère les détails de l'enregistrement des objets d'aide et
les chemins de ces aides, ainsi que la récupération des aides à la demande.
Pour enregistrer une aide dans le gestionnaire, utilisez addHelper :
Zend_Controller_Action_HelperBroker::addHelper($helper);
Bien sûr, instancier et fournir des aides au gestionnaire est coûteux en temps et en ressource donc deux
méthodes existent pour automatiser les choses légèrement : addPrefix() et
addPath().
-
addPrefix()prend un préfixe de classe et l'utilise pour déterminer le chemin des dossiers dans lesquels les classes d'aides ont été définies. Ceci suppose que le préfixe de la classe respecte la convention de nommage du Zend Framework.// Ajoute les aides préfixées Mes_Action_Helpers dans Mes/Action/Helpers/
Zend_Controller_Action_HelperBroker::addPrefix('Mes_Action_Helpers'); -
addPath()prend un répertoire en premier argument et un préfixe de classe en second (par défaut réglé à "Zend_Controller_Action_Helper"). Ceci vous permet de faire correspondre vos propres préfixes de classe à vos dossiers spécifiques.// Ajoute les aides préfixées avec Aide dans Plugins/Aides/
Zend_Controller_Action_HelperBroker::addPath('./Plugins/Aides', 'Aide');
Puisque ces méthodes sont statiques, elles peuvent être appelées en tout point du déroulement du contrôleur pour ajouter dynamiquement les aides nécessaires.
Pour déterminer si une aide existe dans le gestionnaire d'aide, utilisez hasHelper($name), où
$name est le nom raccourci de l'aide (sans le préfixe) :
// Vérifie si l'aide 'redirector' est enregistrée dans le gestionnaire :
if (Zend_Controller_Action_HelperBroker::hasHelper('redirector')) {
echo 'L\'aide Redirector est enregistrée';
}
Il existe aussi deux méthodes statiques pour récupérer les aides issues du gestionnaire d'aide :
getExistingHelper() et getStaticHelper(). getExistingHelper() récupérera
une aide seulement si elle a précédemment été invoquée par ou explicitement enregistrée dans le gestionnaire
d'aides; la méthode lèvera une exception sinon. getStaticHelper() réalise la même chose que
getExistingHelper(), mais tentera d'instancier l'aide si elle n'a pas déjà été enregistrée dans la
pile des aides. getStaticHelper() est un bon choix pour récupérer les aides que vous voulez
configurer.
Les deux méthodes prennent un unique paramètre, $name, qui est le nom court de l'aide
(c'est-à-dire sans le préfixe).
// Vérifie si l'aide 'redirector' est enregistrée dans le gestionnaire, et l'extrait :
if (Zend_Controller_Action_HelperBroker::hasHelper('redirector')) {
$redirector = Zend_Controller_Action_HelperBroker::getExistingHelper('redirector');
}
// Ou, simplement le récupère, sans se soucier s'il a ou non été
// enregistré précédemment :
$redirector = Zend_Controller_Action_HelperBroker::getStaticHelper('redirector');
}
Enfin, pour effacer une aide enregistrée du gestionnaire, utilisez removeHelper($name), où
$name est le nom raccourci de l'aide (sans le préfixe) :
// Effacement conditionnel de l'aide 'redirector' du gestionnaire :
if (Zend_Controller_Action_HelperBroker::hasHelper('redirector')) {
Zend_Controller_Action_HelperBroker::removeHelper('redirector')
}
Le Zend Framework inclue plusieurs aides d'action par défaut : AutoComplete pour des réponses
automatiques à des auto-complétions AJAX ; ContextSwitch et AjaxContext pour
distribuer des formats de réponse alternatifs pour vos actions ; FlashMessenger pour gérer des
messages entre les sessions ; Redirector, qui fournit différentes implémentations pour rediriger
vers des pages internes ou externes à votre application ; et ViewRenderer pour automatiser le
processus de paramétrage de vos objets de vues dans votre contrôleur et du rendu de ces vues.
L'aide ActionStack vous permet d'empiler les requêtes dans le plugin de contrôleur frontal ActionStack, vous aidant effectivement à créer une
liste d'actions à exécuter durant la requête. Cette aide vous permet d'ajouter des actions, soit en spécifiant de
nouveaux objets de requêtes, soit en paramétrant action/controller/module.
![]() |
Invoquer l'aide ActionStack initialise le plugin ActionStack |
|---|---|
L'appel de l'aide |
Exemple 8.2. Ajouter une tâche en utilisant une action, un contrôleur et un module
Souvent, il est plus simple de spécifier l'action, le contrôleur et le module (et optionnellement des
paramètres de requêtes), comme vous le feriez en appelant Zend_Controller_Action::_forward()
:
class FooController extends Zend_Controller_Action
{
public function barAction()
{
// Ajoute deux actions à la pile
// Ajoute un appel à /foo/baz/bar/baz
// (FooController::bazAction() avec une variable de requête bar == baz)
$this->_helper->actionStack('baz', 'foo', 'default', array('bar' => 'baz'));
// Ajoute un appel à /bar/bat
// (BarController::batAction())
$this->_helper->actionStack('bat', 'bar');
}
}
Exemple 8.3. Ajouter une tâche en utilisant un objet de requête
Parfois la nature OO d'un objet de requête a plus de sens ; vous pouvez alors fournir l'objet à l'aide
ActionStack.
class FooController extends Zend_Controller_Action
{
public function barAction()
{
// Ajoute deux actions à la pile
// Ajoute un appel à /foo/baz/bar/baz
// (FooController::bazAction() avec une variable de requête bar == baz)
$request = clone $this->getRequest();
$request->setActionName('baz') // sans régler le contrôleur ou le module
->setParams(array('bar' => 'baz')); // utilise les valeurs courantes
$this->_helper->actionStack($request);
// Ajoute un appel à /bar/bat
// (BarController::batAction())
$request = clone $this->getRequest();
$request->setActionName('bat') // sans régler le module
->setControllerName('bar'); // utilise la valeur courante
$this->_helper->actionStack($request);
}
}
Beaucoup de librairies javascript AJAX propose une fonctionnalité dite d'auto-complétion. Une liste de
résultats possibles est chargée par AJAX au fur et à mesure que l'utilisateur saisit. L'aide
AutoComplete est destinée à simplifier le retour de ces valeurs vers la librairie Javascript.
Toutes les librairies JS n'implémentant pas l'auto-complétion de la même manière, l'aide
AutoComplete propose une solution abstraite, ainsi que des implémentations concrètes pour certaines
librairies. Les types de valeur de retour sont en général des tableaux de chaînes JSON, des tableaux de tableaux
JSON, ou du HTML.
L'utilisation basique ressemble à ceci :
class FooController extends Zend_Controller_Action
{
public function barAction()
{
// Ici du travail ....
// Encode et envoie la réponse
$this->_helper->autoCompleteDojo($data);
// Ou :
$response = $this->_helper->autoCompleteDojo->sendAutoCompletion($data);
// Ou alors prépare simplement les données :
$response = $this->_helper->autoCompleteDojo->prepareAutoCompletion($data);
}
}
Par défaut, l'auto-complétion :
Désactive les layouts et le ViewRenderer.
Affecte des en-têtes de réponse appropriés.
Remplit le corps de la réponse avec les données d'auto-complétion encodées/formatées.
Envoie la réponse.
Les méthodes disponibles sont :
disableLayouts()est utilisée pour désactiver les layouts et le ViewRenderer. Cette méthode est appelées parprepareAutoCompletion().encodeJson($data, $keepLayouts = false)va encoder les données en JSON. Cette méthode est appelées parprepareAutoCompletion().prepareAutoCompletion($data, $keepLayouts = false)prépare les données dans le format de réponse nécessaire à une implémentation concrète. La valeur de retour va changer en fonction de l'implémentation (de la librairie AJAX utilisée).sendAutoCompletion($data, $keepLayouts = false)Va appelerprepareAutoCompletion(), puis envoyer la réponse.direct($data, $sendNow = true, $keepLayouts = false)est une méthode utilisée par le gestionnaire d'aides (helper broker). La valeur de$sendNowva déterminer si c'estsendAutoCompletion()ouprepareAutoCompletion(), qui doit être appelée.
Actuellement, AutoComplete supporte les librairies AJAX Dojo et Scriptaculous.
Dojo n'a pas une fonctionnalité d'auto-complétion, mais deux : ComboBox et
FilteringSelect. Dans les deux cas, elle demande une structure de données qui implémente
QueryReadStore ; voyez la documentation de dojo.data
Dans le Zend Framework, vous pouvez passer un simple tableau indexé à l'aide
AutoCompleteDojo, elle retournera une réponse JSON compatible avec la structure de données Dojo
:
// à l'intérieur d'une action de contrôleur :
$this->_helper->autoCompleteDojo($data);
Exemple 8.4. AutoCompletion avec Dojo en utilisant MVC
L'auto-complétion avec Dojo via MVC requière plusieurs choses: générer un objet formulaire sur le
ComboBox sur lequel vous voulez de l'auto-complétion, un contrôleur avec une action pour servir
les résultats, la création d'un QueryReadStore à connecter à l'action et la génération du
javascript à utiliser pour initialiser l'auto-complétion coté serveur.
Voyons le javascript nécessaire. Dojo est une librairie qui propose des objets haut niveau pour
l'auto-complétion (entre autres), un peu comme le Zend Framework pour PHP. Il est possible de créer des
pseudo-namespaces en utilisant l'arborescence des répertoires. Nous allons créer un répertoire "custom" au
même niveau que le répertoire Dojo. A l'intérieur, nous allons créer un fichier javascript,
TestNameReadStore.js, avec le contenu suivant :
dojo.provide("custom.TestNameReadStore");
dojo.declare("custom.TestNameReadStore", dojox.data.QueryReadStore, {
fetch:function (request) {
request.serverQuery = { test:request.query.name };
return this.inherited("fetch", arguments);
}
});
Cette classe est une simple extension de QueryReadStore, qui est une classe abstraite.
Nous définissons simplement une méthode de requête, et on lui assigne notre élément "test".
Ensuite, créons le formulaire sur lequel nous souhaitons une auto-complétion :
class TestController extends Zend_Controller_Action
{
protected $_form;
public function getForm()
{
if (null === $this->_form) {
require_once 'Zend/Form.php';
$this->_form = new Zend_Form();
$this->_form->setMethod('get')
->setAction($this->getRequest()->getBaseUrl() . '/test/process')
->addElements(array(
'test' => array('type' => 'text', 'options' => array(
'filters' => array('StringTrim'),
'dojoType' => array('dijit.form.ComboBox'),
'store' => 'testStore',
'autoComplete' => 'false',
'hasDownArrow' => 'true',
'label' => 'Your input:',
)),
'go' => array('type' => 'submit', 'options' => array('label' => 'Go!'))
));
}
return $this->_form;
}
}
Ici, nous créons simplement un formulaire avec des méthodes "test" et "go". La méthode "test" ajoute
plusieurs attributs Dojo spéciaux : dojoType, store, autoComplete, et
hasDownArrow. dojoType est utilisé pour indiquer la création d'une
ComboBox, et nous allons la relier au conteneur de données ("store") de
"testStore". Mettre "autoComplete" à false dit à Dojo de ne pas
sélectionner automatiquement la première valeur, mais de plutôt montrer une liste de valeurs possibles.
Enfin, "hasDownArrow" crée une flèche bas comme sur les select box.
Ajoutons une méthode pour afficher le formulaire, et une entrée pour traiter l'auto-complétion :
class TestController extends Zend_Controller_Action
{
// ...
/**
* Landing page
*/
public function indexAction()
{
$this->view->form = $this->getForm();
}
public function autocompleteAction()
{
if ('ajax' != $this->_getParam('format', false)) {
return $this->_helper->redirector('index');
}
if ($this->getRequest()->isPost()) {
return $this->_helper->redirector('index');
}
$match = trim($this->getRequest()->getQuery('test', ''));
$matches = array();
foreach ($this->getData() as $datum) {
if (0 === strpos($datum, $match)) {
$matches[] = $datum;
}
}
$this->_helper->autoCompleteDojo($matches);
}
}
Dans autocompleteAction(), nous vérifions que nous avons bien une requête post, et un
paramètre "format" avec la valeur "ajax". Ensuite, nous vérifions la présence d'un
paramètre "test", et le comparons avec nos données. (getData() retourne des
données quelconques.).Enfin, nous envoyons nos résultats à notre aide AutoCompletion.
Voyons maintenant notre script de vue. Nous devons configurer notre entrepôt de données, puis rendre le formulaire, et s'assurer que les librairies Dojo appropriées sont bien chargées (ainsi que notre entrepôt). Voici le script de vue :
<? // configuration de l'entrepôt de données : ?>
<div dojoType="custom.TestNameReadStore" jsId="testStore"
url="<?= $this->baseUrl() ?>/unit-test/autocomplete/format/ajax" requestMethod="get"></div>
<? // rendu du formulaire : ?>
<?= $this->form ?>
<? // configuration des CSS de Dojo dans le head HTML : ?>
<? $this->headStyle()->captureStart() ?>
@import "<?= $this->baseUrl() ?>/javascript/dijit/themes/tundra/tundra.css";
@import "<?= $this->baseUrl() ?>/javascript/dojo/resources/dojo.css";
<? $this->headStyle()->captureEnd() ?>
<? // configuration de javascript pour charger les librairies Dojo dans le head HTML : ?>
<? $this->headScript()
->setAllowArbitraryAttributes(true)
->appendFile($this->baseUrl() . '/javascript/dojo/dojo.js',
'text/javascript',
array('djConfig' => 'parseOnLoad: true'))
->captureStart() ?>
djConfig.usePlainJson=true;
dojo.registerModulePath("custom","../custom");
dojo.require("dojo.parser");
dojo.require("dojox.data.QueryReadStore");
dojo.require("dijit.form.ComboBox");
dojo.require("custom.TestNameReadStore");
<? $this->headScript()->captureEnd() ?>
Notez les appels aux aides de vue comme headStyle et headScript.
Nous pouvons dès lors faire fonctionner l'auto-complétion Dojo.
Scriptaculous attend une réponse HTML dans un format spécifique.
Utilisez l'aide "AutoCompleteScriptaculous". Passez lui un tableau de données et l'aide
créera une réponse HTML compatible avec Ajax.Autocompleter.
L'aide d'action ContextSwitch est destinée à faciliter le retour de différents formats de réponse
à une requête.L'AjaxContext est une aide spécialisée de ContextSwitch qui permet le renvoi
de réponses à XmlHttpRequest.
Pour l'activer, vous devez indiquer à votre contrôleur quelles actions répondent à quel contexte. Si une requête d'entrée indique un contexte valide pour une action, alors l'aide d'action en charge :
Va désactiver les Layouts, si elles sont activées (
Zend_Layout).Va changer le suffixe de la vue à rendre, il faudra donc créer une vue par contexte.
Va envoyer les bons en-têtes de réponse en fonction du contexte désiré.
Va éventuellement en option appeler des fonctions pour configurer le contexte, ou des fonctions de post-processing.
Comme exemple, prenons le contrôleur suivant :
class NewsController extends Zend_Controller_Action
{
/**
* page d'arrivée; forward vers listAction()
*/
public function indexAction()
{
$this->_forward('list');
}
/**
* Liste les news
*/
public function listAction()
{
}
/**
* Affiche une new particulière
*/
public function viewAction()
{
}
}
Imaginons que nous voulions que listAction() soit aussi accessible au format XML. Plutôt que de
créer une autre action, nous pouvons lui indiquer qu'elle doit retourner du XML :
class NewsController extends Zend_Controller_Action
{
public function init()
{
$contextSwitch = $this->_helper->getHelper('contextSwitch');
$contextSwitch->addActionContext('list', 'xml')
->initContext();
}
// ...
}
Ce code aura pour effet:
De changer le "Content-Type" de la réponse en "text/xml".
De changer le suffixe de vue vers "xml.phtml" (ou un autre suffixe si vous en utilisez un personnalisé "xml.[votre suffixe]").
Il est donc nécessaire de créer un nouveau script de vue, "news/list.xml.phtml", qui créera et rendra le XML.
Pour savoir si la requête doit utiliser un contexte switch, l'aide vérifie un jeton dans l'objet de requête. Par défaut, l'aide va chercher le paramètre de requête "format", ceci peut être changé. Ceci signifie que dans la plupart des cas, pour changer le contexte d'une réponse, il faut simplement injecter un paramètre "format" à la requête:
Via l'URL :
/news/list/format/xml(le routeur par défaut utilise les paramètres dans ce style : {...}/action/parametre/valeur)Via un paramètre GET :
/news/list?format=xml
ContextSwitch vous permet d'écrire des contextes, ceux-ci spécifient le suffixe de vue qui
change, les en-têtes HTTP de réponse à modifier, et les fonctions de rappel éventuelles.
Par défaut, il existe 2 contextes dans l'aide ContextSwitch : json et xml.
-
JSON. Le contexte JSON met le "Content-Type" de la réponse à "application/json", et le suffixe de la vue est "json.phtml".
Par défaut cependant, aucun script de vue n'est nécessaire, il va simplement sérialiser en JSON toutes les variables de vues, et les envoyer en tant que réponse.
Ce comportement peut être désactivé en passant le paramètre de sérialisation à
false:$this->_helper->contextSwitch()->setAutoJsonSerialization(false); XML. Le contexte XML met le "Content-Type" de la réponse à "text/xml", et utilise un suffixe de vue "xml.phtml". Vous devrez créer une nouvelle vue pour ce contexte.
Vous pouvez créer vos propres contextes d'action. Par exemple pour retourner du YAML, du PHP sérialisé, ou
encore du RSS ou du ATOM. ContextSwitch est là pour cela.
La manière la plus simple d'ajouter un nouveau contexte d'action est la méthode addContext().
Elle prend 2 paramètres : le nom du contexte, et un tableau d'options. Ce tableau d'option doit comporter au
moins une des clés suivantes :
suffix : Le préfixe qui va s'ajouter au suffixe de vue. Il sera utiliser par le ViewRenderer.
headers : un tableau d'en-têtes/valeurs que vous voulez ajouter à la réponse.
-
callbacks : un tableau dont les clés peuvent être "init" ou "post", et les valeurs représentent des noms de fonctions PHP valides, qui seront utilisées pour initialiser ou traiter la fin du contexte.
Les fonctions d'initialisation interviennent lorsque le contexte est détecté par
ContextSwitch. Par exemple dans le contexte intégré JSON, la fonction désactive le ViewRenderer lorsque la sérialisation automatique est activée.Les fonctions de traitement de fin de contexte (Post processing) interviennent durant le processus de
postDispatch()de l'action en cours. Par exemple pour le contexte intégré JSON, la fonction de post process regarde si la sérialisation automatique est demandée, si c'est le cas, elle va sérialiser les variables de la vue en JSON, et envoyer la réponse; mais dans le cas contraire, elle va réactiver le ViewRenderer.
Voici les méthodes d'interaction avec les contextes :
addContext($context, array $spec): Ajoute un nouveau contexte. Si celui-ci existe déjà, une exception sera lancée.setContext($context, array $spec): Ajoute un nouveau contexte, mais écrase celui-ci s'il existait déjà. Utilise les mêmes spécifications queaddContext().addContexts(array $contexts): Ajoute plusieurs contextes d'un coup. Le tableau$contextsdoit être un tableau de paires contexte/specifications. Si un des contextes existe déjà, une exception est lancée.setContexts(array $contexts): Ajoute des nouveaux contextes, mais écrase ceux déjà présents éventuellement. Utilise les mêmes spécifications queaddContexts().hasContext($context): retournetruesi le contexte existe déjà,falsesinon.getContext($context): retourne un contexte par son nom. Le retour est un tableau qui a la même syntaxe que celui utilisé paraddContext().getContexts(): retourne tous les contextes. Le tableau de retour est de la forme contexte => spécifications.removeContext($context): Supprime un contexte grâce à son nom. Retournetruesi réussi,falsesi le contexte n'a pas été trouvé.clearContexts(): Supprime tous les contextes.
Il existe deux mécanismes pour créer et affecter des contextes. Vous pouvez créer des tableaux dans vos
contrôleurs, ou utiliser plusieurs méthodes de ContextSwitch pour les assembler.
La méthode principale pour ajouter des contextes à des actions est addActionContext(). Elle
attend 2 arguments, l'action et le contexte (ou un tableau de contextes). Par exemple, considérons la classe
suivante :
class FooController extends Zend_Controller_Action
{
public function listAction()
{
}
public function viewAction()
{
}
public function commentsAction()
{
}
public function updateAction()
{
}
}
Imaginons que nous voulions ajouter un contexte XML à l'action "list", et deux contextes XML et JSON à
l'action "comments". Nous pourrions faire ceci dans la méthode init() :
class FooController extends Zend_Controller_Action
{
public function init()
{
$this->_helper->contextSwitch()
->addActionContext('list', 'xml')
->addActionContext('comments', array('xml', 'json'))
->initContext();
}
}
De la même manière, il est aussi possible de simplement définir la propriété
$contexts:
class FooController extends Zend_Controller_Action
{
public $contexts = array(
'list' => array('xml'),
'comments' => array('xml', 'json')
);
public function init()
{
$this->_helper->contextSwitch()->initContext();
}
}
Cette syntaxe est simplement moins pratique et plus prompte aux erreurs.
Pour construire vos contextes, les méthodes suivantes vous seront utiles :
-
addActionContext($action, $context): Ajoute un ou plusieurs contextes à une action.$contextdoit donc être une chaîne, ou un tableau de chaînes.Passer la valeur
truecomme contexte marquera tous les contextes comme disponibles pour cette action.Une valeur vide pour
$contextdésactivera tous les contextes donnés à cette action. setActionContext($action, $context): Marque un ou plusieurs contextes comme disponibles pour cette action. Si ceux-ci existent déjà, ils seront remplacés.$contextdoit être une chaîne ou un tableau de chaînes.addActionContexts(array $contexts): Ajoute plusieurs paires action/context en une fois.$contextsdoit être un tableau associatif action/contexte. Cette méthode proxie versaddActionContext().setActionContexts(array $contexts): agit commeaddActionContexts(), mais écrase les paires action/contexte existantes.hasActionContext($action, $context): détermine si une action possède un contexte donné.getActionContexts($action = null): Retourne tous les contextes d'une action donnée, si pas d'action passée, retourne alors toutes les paires action/contexte.removeActionContext($action, $context): Supprime un ou plusieurs contextes pour une action.$contextdoit être une chaîne ou un tableau de chaînes.clearActionContexts($action = null): Supprime tous les contextes d'une action. Si aucune action n'est spécifiée, supprime alors tous les contextes de toutes les actions.
Pour initialiser la permutation de contextes (contexte switching), vous devez appeler
initContext() dans vos contrôleurs d'action :
class NewsController extends Zend_Controller_Action
{
public function init()
{
$this->_helper->contextSwitch()->initContext();
}
}
Dans certains cas, vous voudriez forcer un contexte pour une action et n'autoriser que celui-ci. Passez le
alors à initContext() :
$contextSwitch->initContext('xml');
Voici quelques méthodes qui peuvent être utilisées pour changer le comportement de l'aide
ContextSwitch :
-
setAutoJsonSerialization($flag): Par défaut, le contexte JSON va sérialiser toute variable en notation JSON et les retourner en tant que réponse. Si vous voulez créer votre propre réponse, vous voudriez désactiver cet effet. Ceci doit être fait avant l'appel àinitContext().$contextSwitch->setAutoJsonSerialization(false);
$contextSwitch->initContext();Pour récupérer la valeur actuelle, utilisez
getAutoJsonSerialization(). -
setSuffix($context, $suffix, $prependViewRendererSuffix): Cette méthode permet de personnaliser le suffixe de vue d'un contexte. Le troisième argument indique si le suffixe actuel du ViewRenderer doit être utilisé comme préfixe de votre suffixe. Par défaut, c'est le cas.Passer une valeur vide au suffixe aura pour effet de n'utiliser que le suffixe du ViewRenderer.
-
addHeader($context, $header, $content): Ajoute un en-tête à la réponse pour un contexte donné.$headerest le nom de l'en-tête et$contentsa valeur.Chaque contexte peut posséder plusieurs en-têtes,
addHeader()ajoute des en-têtes dans une pile, pour un contexte donné.Si l'en-tête spécifié pour le contexte existe déjà, une exception sera alors levée.
setHeader($context, $header, $content):setHeader()agit commeaddHeader(), sauf qu'il va écraser un en-tête qui aurait déjà été présent.addHeaders($context, array $headers): Ajoute plusieurs en-têtes en une seule fois. Proxie versaddHeader().$headersest un tableau de paires header => contexte.setHeaders($context, array $headers.): commeaddHeaders(), sauf que cette méthode proxie verssetHeader(), vous permettant d'écraser des en-têtes déjà présents.getHeader($context, $header): retourne une valeur d'en-tête pour un contexte. Retournenullsi non trouvé.removeHeader($context, $header): supprime un en-tête d'un contexte.clearHeaders($context, $header): supprime tous les en-têtes d'un contexte.setCallback($context, $trigger, $callback): affecte une fonction de rappel (callback) pour un contexte.$triggerpeut être soit "init" ou "post" (la fonction de rappel sera appelée soit à l'initialisation du contexte, ou à la fin, en postDispatch).$callbackdoit être un nom de fonction PHP valide.setCallbacks($context, array $callbacks): affecte plusieurs fonctions de rappel pour un contexte.$callbacksdoit être un tableau de paires trigger/callback. Actuellement, seules deux fonctions maximum peuvent être enregistrées car il n'existe que 2 déclencheurs (triggers) : "init" et "post".getCallback($context, $trigger): retourne un nom de fonction de rappel affectée à un contexte.getCallbacks($context): retourne un tableau de paires trigger/callback pour un contexte.removeCallback($context, $trigger): supprime une fonction de rappel d'un contexte.clearCallbacks($context): supprime toutes les fonctions de rappel d'un contexte.-
setContextParam($name): affecte le paramètre de requête à vérifier pour savoir si un contexte a été appelé. La valeur par défaut est "format".getContextParam()en retourne la valeur actuelle. -
setAutoDisableLayout($flag): Par défaut, les layouts sont désactivées lorsqu'un contexte intervient, ceci provient du fait que les layouts n'ont en théorie pas de signification particulière pour un contexte, mais plutôt pour une réponse 'normale'. Cependant si vous désirez utiliser les layouts pour des contexte, passez alors la valeurfalseà cette méthode. Ceci devant être fait avant l'appel àinitContext().Pour récupérer la valeur de ce paramètre, utilisez
getAutoDisableLayout(). getCurrentContext()est utilisée pour savoir quel contexte a été détecté (si c'est le cas). Cette méthode retournenullsi aucune permutation de contexte a été détectée, ou si elle est appelée avantinitContext().
L'aide AjaxContext étend l'aide de permutation de contexte ContextSwitch, donc
toutes ses fonctionnalités s'y retrouvent. Il y a cependant quelques différences :
Cette aide utilise une propriété de contrôleur d'action différente pour déterminer les contextes,
$ajaxable. Vous pouvez avoir différents contextes utilisés avec les requêtes AJAX. Les différentes
méthodes *ActionContext*() de AjaxContext vont écrire dans cette propriété.
De plus, cette aide ne sera déclenchée que si la requête répond au critère
isXmlHttpRequest(). Donc même si le paramètre "format" est passée à la requête, il faut
nécessairement que celle ci soit une requête XmlHttpRequest, sinon la permutation d'AjaxContext
n'aura pas lieu.
Enfin, AjaxContext ajoute un contexte, HTML. Dans ce contexte, le suffixe de vue est
"ajax.phtml". Il n'y a pas d'en-tête particulier ajouté à la réponse.
Exemple 8.5. Autoriser les actions à répondre aux requêtes AJAX
Dans l'exemple qui suit, nous autorisons les actions "view", "form", et "process" à répondre aux requêtes AJAX. Dans les actions, "view" et "form", nous retournerons des portions de HTML; dans "process", nous retournerons du JSON.
class CommentController extends Zend_Controller_Action
{
public function init()
{
$ajaxContext = $this->_helper->getHelper('AjaxContext');
$ajaxContext->addActionContext('view', 'html')
->addActionContext('form', 'html')
->addActionContext('process', 'json')
->initContext();
}
public function viewAction()
{
// Voir les commentaires.
// Quand le AjaxContext est détecté, il utilise le script de vue
// comment/view.ajax.phtml
}
public function formAction()
{
// Rend les formulaire "ajoutez un commentaire".
// Lorsque le AjaxContext est détecté, il utilise le script de vue
// comment/form.ajax.phtml
}
public function processAction()
{
// Traite un commentaire
// Retourne les résultats sous forme JSON; assignez simplement vos résultats comme
// variables de vues.
}
}
Coté client, votre bibliothèque AJAX requêtera simplement "/comment/view", "/comment/form", et "/comment/process", en passant le paramètre "format" : "/comment/view/format/html", "/comment/form/format/html", "/comment/process/format/json". (Ceci fonctionne aussi avec "?format=json".)
Il est nécessaire que votre bibliothèque envoie l'en-tête HTTP "X-Requested-With: XmlHttpRequest", ce qui est en général le cas.
L'aide FlashMessenger vous permet de fournir les messages dont l'utilisateur pourrait avoir
besoin dans la requête suivante. Pour accomplir ceci, FlashMessenger utilise
Zend_Session_Namespace pour stocker les messages à retrouver dans la prochaine requête. C'est
généralement une bonne idée si vous planifiez d'utiliser Zend_Session ou
Zend_Session_Namespace, que vous initialisez avec Zend_Session::start() dans votre
fichier d'amorçage. (Reportez vous à la documentation de Zend_Session pour plus de détails sur son
utilisation.)
L'exemple ci-dessous vous montre l'utilisation du flash messenger dans sa forme la plus basique. Quand
l'action /some/my est appelée, il ajoute le message "Sauvegarde réalisée !". Une requête suivante
vers l'action /some/my-next-request le retrouvera (ainsi que le détruira).
class SomeController extends Zend_Controller_Action
{
/**
* FlashMessenger
*
* @var Zend_Controller_Action_Helper_FlashMessenger
*/
protected $_flashMessenger = null;
public function init()
{
$this->_flashMessenger = $this->_helper->getHelper('FlashMessenger');
$this->initView();
}
public function myAction()
{
/**
* Méthode par défaut por obtenir l'instance de
* Zend_Controller_Action_Helper_FlashMessenger à la demande
*/
$this->_flashMessenger->addMessage('Sauvegarde réalisée !');
}
public function myNextRequestAction()
{
$this->view->messages = $this->_flashMessenger->getMessages();
$this->render();
}
}
Les réponses JSON sont les réponses de choix dans une architecture de type AJAX qui attend des données structurées. JSON peut être immédiatement interprété du coté du client, ce qui rend la tâche plus simple et plus rapide.
L'aide d'action JSON effectue plusieurs traitements :
Désactive les layouts si elles sont activées.
Désactive le ViewRenderer s'il est activé.
Envoie à la réponse un en-tête 'Content-Type' à 'application/json'.
Par défaut, retourne immédiatement la réponse, sans attendre la fin de l'exécution de l'action.
Son utilisation est toute simple, appelez le depuis le gestionnaire d'aides (Broker), ou appelez une de ses
méthodes encodeJson() ou sendJson():
class FooController extends Zend_Controller_Action
{
public function barAction()
{
// Effectue des traitements ici ...
// Envoie la réponse JSON :
$this->_helper->json($data);
// ou...
$this->_helper->json->sendJson($data);
// ou retourne la chaine json:
$json = $this->_helper->json->encodeJson($data);
}
}
![]() |
Conserver les Layouts |
|---|---|
|
Si vous avez besoin des layouts, pour par exemple générer vos réponses JSON dans un contexte particulier,
chaque méthode de l'aide JSON accepte un second paramètre booléen. A
|
L'aide Redirector vous permet d'utiliser un objet de redirection qui remplit tous les besoins
de votre application, nécessaires à une redirection vers une nouvelle URL. Il fournit de nombreux avantages par
rapport à la méthode _redirect(), comme la capacité de préconfigurer le comportement du site dans
l'objet Redirector ou d'utiliser l'interface intégrée gotoSimple($action, $controller,
$module, $params) similaire à Zend_Controller_Action::_forward().
Redirector possède une certain nombre de méthodes qui peuvent être utilisées pour affecter le
comportement de la redirection :
setCode()peut être utilisée pour paramétrer le code HTTP de la réponse à utiliser pendant la redirection.setExit()peut être utilisée pour forcer unexit()juste après la redirection. Par défaut ceci vauttrue.setGotoSimple()peut être utilisée pour paramétrer l'URL par défaut à utiliser si aucune n'est fournie àgotoSimple(). Elle utilise les API deZend_Controller_Action::_forward():setGotoSimple($action, $controller = null, $module = null, array $params = array());setGotoRoute()peut être utilisée pour paramétrer une URL basée sur une route enregistrée. Fournissez un tableau de paires clé/valeur et une route nommée, et elle assemblera une URL suivant le type de la route et sa définition.setGotoUrl()peut être utilisée pour paramétrer l'URL par défaut à utiliser si aucune n'est fournie àgotoUrl(). Accepte une chaîne unique correspondant à une URL.setPrependBase()peut être utilisée pour ajouter une chaîne au début de l'URL de base de l'objet requête pour les URLs spécifiées avecsetGotoUrl(),gotoUrl(), ougotoUrlAndExit().setUseAbsoluteUri()peut être utilisée pour forcer leRedirectorà utiliser des URI absolus pour la redirection. Quand cette option est choisie, elle utilise les valeurs de$_SERVER['HTTP_HOST'],$_SERVER['SERVER_PORT'], et$_SERVER['HTTPS']pour former un URI complet à partir de l'URL spécifiée par une des méthodes de redirection. Cette option est inactive par défaut, mais pourra être activée par défaut dans les prochaines releases.
De plus, il y a une variété de méthodes dans le Redirector pour réaliser les redirections
actuelles :
gotoSimple()utilisesetGotoSimple()(API de type _forward()) pour construire une URL et réaliser une redirection.gotoRoute()utilisesetGotoRoute()(assemblage de route) pour construire une URL et réaliser une redirection.gotoUrl()utilisesetGotoUrl()(URL sous forme de chaîne) pour construire une URL et réaliser une redirection.
Enfin, vous pouvez déterminer l'URL de la redirection courante à tout moment en utilisant
getRedirectUrl().
Exemple 8.6. Options de réglage
Cet exemple surcharge de multiples options, incluant le réglage du code de statut HTTP à utiliser dans
la redirection ("303"), le retrait du exit par défaut après la redirection, et la définition
d'une URL par défaut à utiliser lors d'une redirection.
class SomeController extends Zend_Controller_Action
{
/**
* Redirector - défini pour l'auto-complétion
*
* @var Zend_Controller_Action_Helper_Redirector
*/
protected $_redirector = null;
public function init()
{
$this->_redirector = $this->_helper->getHelper('Redirector');
// Régle les options par défaut pour le redirector
// Puisque l'objet est enregistré dans le gestionnaire d'aide, ceci sera effectif
// pour toutes les actions réalisées après ce point
$this->_redirector->setCode('303')
->setExit(false)
->setGotoSimple("this-action", "some-controller");
}
public function myAction()
{
/* Faire quelquechose */
// Redirige vers une URL enregistrée précédemment, et force une sortie pour finir
$this->_redirector->redirectAndExit();
return; // jamais atteint
}
}
Exemple 8.7. Utiliser les valeurs par défaut
Cet exemple suppose que vous utilisez les paramètres par défaut, ce qui inclut que toute redirection
sera suivie d'un exit() immédiat.
// EXEMPLE ALTERNATIF
class AlternativeController extends Zend_Controller_Action
{
/**
* Redirector - défini pour l'auto-complétion
*
* @var Zend_Controller_Action_Helper_Redirector
*/
protected $_redirector = null;
public function init()
{
$this->_redirector = $this->_helper->getHelper('Redirector');
}
public function myAction()
{
/* Faire quelquechose */
$this->_redirector->gotoUrl('/my-controller/my-action/param1/test/param2/test2');
return; // jamais atteint puisque les paramètres par défaut sont à goto et exit
}
}
Exemple 8.8. Utilisation de l'API _forward() de goto()
L'API de gotoSimple() imite celle de Zend_Controller_Action::_forward(). La
différence principale est qu'elle construit une URL à partir des paramètres fournis, et du format de route
par défaut :module/:controller/:action/* du routeur. Il réalise alors une redirection au lieu
d'enchaîner l'action.
class ForwardController extends Zend_Controller_Action
{
/**
* Redirector - défini pour l'auto-complétion
*
* @var Zend_Controller_Action_Helper_Redirector
*/
protected $_redirector = null;
public function init()
{
$this->_redirector = $this->_helper->getHelper('Redirector');
}
public function myAction()
{
/* Faire quelquechose */
// Redirige vers 'my-action' de 'my-controller' dans le module courant
// en utilisant les paramètres param1 => test et param2 => test2
$this->_redirector->gotoSimple('my-action', 'my-controller', null, array('param1' => 'test', 'param2' => 'test2'));
}
}
Exemple 8.9. Utilisation de l'assemblage de la route avec gotoRoute()
L'exemple suivant utilise la méthode assemble() du routeur pour créer une URL basée sur un tableau associatif de
paramètres fournis. Il suppose que la route suivante a été enregistrée :
$route = new Zend_Controller_Router_Route(
'blog/:year/:month/:day/:id',
array('controller' => 'archive', 'module' => 'blog', 'action' => 'view')
);
$router->addRoute('blogArchive', $route);
En donnant un tableau avec l'année réglée à 2006, le mois à 4, le jour à 24 et l'ID à 42, il
construira l'URL /blog/2006/4/24/42.
class BlogAdminController extends Zend_Controller_Action
{
/**
* Redirector - défini pour l'auto-complétion
*
* @var Zend_Controller_Action_Helper_Redirector
*/
protected $_redirector = null;
public function init()
{
$this->_redirector = $this->_helper->getHelper('Redirector');
}
public function returnAction()
{
/* Faire quelquechose */
// Redirige vers les archives de blog. Construit l'URL suivante:
// /blog/2006/4/24/42
$this->_redirector->gotoRoute(
array('year' => 2006, 'month' => 4, 'day' => 24, 'id' => 42),
'blogArchive'
);
}
}
L'aide ViewRenderer apporte les comportements suivants :
Élimine le besoin d'instancier un objet de vue dans ses contrôleurs. Ceci devient automatique.
Configure automatiquement les chemins vers les scripts de vue, les aides, et les filtres, en se basant sur le module actuel et associe le nom du module comme préfixe de classe pour les aides et les filtres.
Créer un objet de vue général accessible pour tous les contrôleurs et donc pour toutes les actions disptachées.
Autorise le développeur à personnaliser les options de rendu de la vue.
Donne la possibilité de rendre automatiquement un script de vue.
Donne accès aux paramètres configurant le chemin de base (base path) et le chemin des scripts (script path), de la vue.
![]() |
Note |
|---|---|
Su vous utilisez |
![]() |
Note |
|---|---|
|
Le Si vous voulez modifier un paramètre du
|
L'usage le plus banal consiste à instancier et passer l'objet ViewRenderer au gestionnaire
d'aides. La manière la plus simple est d'utiliser la méthode statique getStaticHelper() du
gestionnaire, qui s'occupe de tout ceci en une passe :
Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
La première action demandée instancie ou récupère l'objet de vue. A chaque instanciation de contrôleur, la
méthode init() de l'objet ViewRenderer est appelée. Elle va configurer la vue et
appeler addScriptPath() avec un chemin relatif au dossier courant. Ceci a pour effet de
"namespacer" toutes les aides et les filtres de vue pour le module en cours.
A chaque postDispatch() d'action, render() est appelée.
Voici un exemple :
// Bar controller , module foo :
class Foo_BarController extends Zend_Controller_Action
{
// Rend bar/index.phtml par défaut; rien à faire c'est automatique
public function indexAction()
{
}
// Rend bar/populate.phtml avec une variable 'foo' à la valeur 'bar'.
// l'objet de vue est défini dans le preDispatch(), il est donc accessible.
public function populateAction()
{
$this->view->foo = 'bar';
}
}
...
// Dans un des scripts de vue :
$this->foo(); // appelle Foo_View_Helper_Foo::foo()
Le ViewRenderer définit de même des accesseurs pour configurer la vue qu'il encapsule
:
setView($view)Passage de l'objet de vue. Il devient accessible comme une propriété publique de l'objet :$view.setNeverRender($flag = true)peut être utilisée pour désactiver le rendu automatique de la vue dans tous les contrôleurs.postDispatch()est alors court-circuitée.getNeverRender()retourne ce paramètre.setNoRender($flag = true)peut être utilisée pour désactiver le rendu automatique de la vue dans le contrôleur actuel.postDispatch()est alors court-circuitée, maispreDispatch()réactive le paramètre pour l'action suivante.getNoRender()retourne cette option.setNoController($flag = true)est utilisée pour spécifier àrender()de ne pas chercher le script de vue dans le sous répertoire après le contrôleur (correspondant à l'action). Par défaut, cette recherche est effectuée.getNoController()retourne ce paramètre.setNeverController($flag = true)fonctionne de manière similaire àsetNoController(), mais pour tous les contrôleurs.getNeverController()est l'autre accesseur.setScriptAction($name)peut être utilisée pour spécifier le script de vue d'une action à rendre.$namedoit être le nom de l'action sans le suffixe (et sans le nom du contrôleur sauf sinoControllera été activé). Si vous n'utilisez pas cette méthode elle cherchera le script de vue correspondant au nom de l'action en cours (issue de l'objet de requête).getScriptAction()retourne la valeur actuelle de ce paramètre.setResponseSegment($name)dit dans quel segment de la réponse rendre le script. Par défaut, la vue est rendue dans le segment par défaut.getResponseSegment()retourne cette valeur.initView($path, $prefix, $options)doit être appelée pour configurer la vue : son "base path", le préfixe de classe pour les filtres et aides, et des options matérialisées par :neverRender,noRender,noController,scriptAction, etresponseSegment.-
setRender($action = null, $name = null, $noController = false)vous permet de spécifier les paramètresscriptAction,responseSegment, etnoControlleren une fois.direct()est un alias qui permet un appel rapide depuis le contrôleur :// Rend 'foo' au lieu du script correspondant à l'action courante
$this->_helper->viewRenderer('foo');
// rend form.phtml dans le segment 'html' de la réponse sans utiliser le
// sous repertoire contrôleur pour chercher le script de vue :
$this->_helper->viewRenderer('form', 'html', true);![[Note]](/images/note.gif)
Note setRender()etdirect()ne rendent pas un script de vue à proprement parler, mais elles notifient aupostDispatch()de le faire.
Le constructeur de ViewRenderer accepte aussi un objet de vue et un tableau d'options, de la
même manière que initView() :
$view = new Zend_View(array('encoding' => 'UTF-8'));
$options = array('noController' => true, 'neverRender' => true);
$viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer($view, $options);
Il est aussi possible de personnaliser les chemins utilisés pour déterminer le base path (chemin de base) de la vue ainsi que le script path (chemin vers les scripts de vue). Des méthodes le permettent, utilisez les options suivantes avec :
:moduleDirreprésente le module courant (par convention le dossier parent au dossier contrôleur).:modulepointe vers le module actuel.:controllerpointe vers le contrôleur actuel.:actionreprésente l'action actuellement traitée.:suffixest utilisée pour le suffixe du script de vue.setViewSuffix()permet aussi de le modifier.
Toutes ces options s'utilisent avec les méthodes ci-après :
setViewBasePathSpec($spec)vous permet de changer le dossier donnant accès aux dossiers de la vue : le base path. Par défaut il s'agit de:moduleDir/views. L'accesseur de récupération estgetViewBasePathSpec().setViewScriptPathSpec($spec)Une fois dans le base path, le rendu cherche le script de vue dans le script path, que cette méthode permet de définir. La valeur par défaut est:controller/:action.:suffixet l'autre accesseur estgetViewScriptPathSpec().setViewScriptPathNoControllerSpec($spec)Une fois dans le base path, sinoControllerest activé, le rendu cherche le script de vue dans le chemin que cette méthode permet de définir. La valeur par défaut est:action.:suffixet l'autre accesseur estgetViewScriptPathNoControllerSpec().
ViewRenderer utilise un inflecteur : Zend_Filter_Inflector, pour résoudre les options de chemin, en chemins
réels. Pour une personnalisation maximale, vous pouvez interagir avec cet inflecteur à l'aide des méthodes
suivantes :
-
getInflector()retourne l'inflecteur. Si aucun n'existe,ViewRendereren crée un avec des options par défaut.Par défaut, les règles de l'inflecteur sont statiques autant pour le suffixe et le répertoire module, que pour la cible. Ceci permet au
ViewRendererde modifier ces valeurs dynamiquement. setInflector($inflector, $reference)peut être utilisée pour passer son propre inflecteur àViewRenderer. Si$referenceest àtrue, alors le suffixe, le répertoire du module et la cible seront affectés en fonction des propriétés deViewRenderer.
![]() |
Règles de résolution par défaut |
|---|---|
|
Le
|
Enfin, l'API ViewRenderer vous propose aussi des méthodes pour déterminer les scripts de vue,
et rendre la vue. Celles-ci se décomposent en :
-
renderScript($script, $name)va vous permettre de spécifier pleinement le script de vue à rendre, et éventuellement un nom de segment de réponse dans lequel rendre.ViewRenderers'attend à un paramètre$scriptreprésentant un chemin complet vers un script de vue, telle que la méthode de la vuerender()l'attend.![[Note]](/images/note.gif)
Note Une fois rendue, la vue utilise
noRenderpour éviter un double rendu automatisé.![[Note]](/images/note.gif)
Note Par défaut,
Zend_Controller_Action::renderScript()est un proxy vers la méthoderenderScript()deViewRenderer. -
getViewScript($action, $vars)récupère le chemin du script de vue en se basant sur les paramètres $action et $vars.$varspeut contenir "moduleDir", "module", "controller", "action", et "suffix"), sinon les valeurs de la requête actuelle seront utilisées.getViewScript()utiliseraviewScriptPathSpecouviewScriptPathNoControllerSpecselon le paramètrenoController.L"inflecteur sera utilisé, par défaut un contrôleur "foo.bar" et une action "baz:bat" amèneront à un script de vue "foo-bar/baz-bat.phtml".
![[Note]](/images/note.gif)
Note Par défaut
Zend_Controller_Action::getViewScript()est un proxy vers la méthodegetViewScript()deViewRenderer. -
render($action, $name, $noController)a beaucoup de responsabilités : d'abord, elle vérifie si$nameou$noControllerlui ont été passés, si c'est le cas, elle configure correctement les paramètresresponseSegmentetnoControllerdans le ViewRenderer. Elle passe ensuite$action, si spécifié, àgetViewScript(). Enfin, elle passe le script de vue calculé àrenderScript().![[Note]](/images/note.gif)
Note Attention aux effets secondaires avec
render(): les valeurs segment de réponse, etnoControllervont persister dans l'objet ViewRenderer. De plus,noRender()va être appelée.![[Note]](/images/note.gif)
Note Par défaut,
Zend_Controller_Action::render()est un proxy versrender()deViewRenderer. renderBySpec($action, $vars, $name)vous fournit le moyen de passer des paramètres de spécification pour le dossier de script de vue. Cette méthode passe$actionet$varsàgetScriptPath(), pour en déduire un chemin qu'elle envoie alors avec$nameàrenderScript().
Exemple 8.10. Usage de base
L'utilisation la plus basique consiste à initialiser ou et enregistrer un objet
ViewRenderer dans le gestionnaire d'aides (helper broker), et ensuite lui passer des variables
dans vos contrôleurs.
// Dans le fichier de démarrage :
Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
...
// 'foo' module, contrôleur 'bar' :
class Foo_BarController extends Zend_Controller_Action
{
// Rend bar/index.phtml par défaut, rien à faire
public function indexAction()
{
}
// Rend bar/populate.phtml avec la variable 'foo' à la valeur 'bar'.
// L'objet de vue est rendu disponible en preDispatch().
public function populateAction()
{
$this->view->foo = 'bar';
}
// Ne rend rien, car on demande un nouveau jeton de dispatching
public function bazAction()
{
$this->_forward('index');
}
// Ne rend rien, une redirection est demandée
public function batAction()
{
$this->_redirect('/index');
}
}
![]() |
Conventions de noms : délimiteurs de mots dans les noms de contrôleur et d'action |
|---|---|
|
Si les noms de votre contrôleur ou de votre action sont composés de plusieurs mots, le dispatcheur
s'attend à ce qu'ils soient séparés par des caractères bien définis, dans l'URL. Le
Notez dans le second exemple, le module est celui par défaut, mais comme un séparateur de chemin
(tiret bas ou "_") est donné, alors le contrôleur dispatché devient |
Exemple 8.11. Désactivation du rendu automatique
Il peut être nécessaire dans certains cas de désactiver manuellement le rendu automatique de vue
effectué par ViewRenderer. Par exemple, si le contrôleur doit retourner une sortie spéciale, comme XML ou
JSON. Deux options s'offrent à vous : setNeverRender()) et setNoRender().
// Baz controller class, bar module :
class Bar_BazController extends Zend_Controller_Action
{
public function fooAction()
{
// Ne rend pas automatiquement cette action
$this->_helper->viewRenderer->setNoRender();
}
}
// Bat controller class, bar module :
class Bar_BatController extends Zend_Controller_Action
{
public function preDispatch()
{
// Ne rend plus aucune action de ce contrôleur
$this->_helper->viewRenderer->setNoRender();
}
}
![]() |
Note |
|---|---|
Utiliser |
Exemple 8.12. Choix d'un script de vue différent
Il peut arriver que vous éprouviez le besoin de rendre un script de vue différent de celui
correspondant à l'action en cours de dispatching. Par exemple, un contrôleur qui possède deux actions ajout
et édition, qui sont susceptibles toutes les deux de rendre le même script de vue. Utilisez alors
setScriptAction(), setRender(), ou appelez l'aide ViewRenderer directement
:
// Bar controller class, foo module :
class Foo_BarController extends Zend_Controller_Action
{
public function addAction()
{
// Rend 'bar/form.phtml' plutôt que 'bar/add.phtml'
$this->_helper->viewRenderer('form');
}
public function editAction()
{
// Rend 'bar/form.phtml' au lieu de 'bar/edit.phtml'
$this->_helper->viewRenderer->setScriptAction('form');
}
public function processAction()
{
// un peu de validation...
if (!$valid) {
// Rend 'bar/form.phtml' à la place de 'bar/process.phtml'
$this->_helper->viewRenderer->setRender('form');
return;
}
// continue le processus...
}
}
Exemple 8.13. Modification de l'objet de vue
Si vous désirez modifier l'objet de vue absorbé par ViewRenderer, pour par exemple
ajouter un chemin vers des aides spécifique, ou spécifier l'encodage, vous pourriez par exemple récupérer
l'objet de vue depuis le ViewRenderer, ou dans un contrôleur.
// Bar controller class, foo module :
class Foo_BarController extends Zend_Controller_Action
{
public function preDispatch()
{
// change l'encodage de la vue
$this->view->setEncoding('UTF-8');
}
public function bazAction()
{
// Récupère l'objet de vue, et lui passe la fonction d'echappement 'htmlspecialchars'
$view = $this->_helper->viewRenderer->view;
$view->setEscape('htmlspecialchars');
}
}
Exemple 8.14. Changement des spécifications de dossier
Dans certains cas, il peut être nécessaire d'utiliser un chemin absolu, fixe. Par exemple si vous ne donnez accès à vos graphistes qu'à un seul dossier, en utilisant un moteur de template tel que Smarty.
Pour ceci, imaginons que le base path soit fixé à "/opt/vendor/templates", et que vous voulez que vos
scripts de vues soit référencés par ":moduleDir/:controller/:action.:suffix"; si le paramètre
noController est activé, vous désirez utiliser le dossier plus haut ":action.:suffix". Enfin,
vous désirez un suffixe en "tpl" :
/**
* Dans le fichier de démarrage :
*/
// Une implémentation personnalisée de la vue
$view = new ZF_Smarty();
$viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer($view);
$viewRenderer->setViewBasePathSpec('/opt/vendor/templates')
->setViewScriptPathSpec(':module/:controller/:action.:suffix')
->setViewScriptPathNoControllerSpec(':action.:suffix')
->setViewSuffix('tpl');
Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);
Exemple 8.15. Rendu de plusieurs scripts de vue dans une même action
Afin de rendre plusieurs scripts de vue dans une même action, appelez tout simplement plusieurs fois
render() :
class SearchController extends Zend_Controller_Action
{
public function resultsAction()
{
// Considérons $this->model comme étant un modèle valide
$this->view->results = $this->model->find($this->_getParam('query', '');
// render() est proxiée vers ViewRenderer
// Rend d'abord un formulaire, puis un résultat
$this->render('form');
$this->render('results');
}
public function formAction()
{
// Rien : ViewRenderer rend automatiquement un script de vue
}
}
