Aides d'action (Helper)
Introduction
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.
Initialisation des aides
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');
$message = 'Nous avons fait quelquechose lors de la dernière requête';
$flashMessenger->addMessage($message);
-
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;
$message = 'Nous avons fait quelquechose lors de la dernière requête';
$flashMessenger->addMessage($message);
-
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 de FlashMessenger , ceci appelle
addMessage() :
$message = 'Nous avons fait quelquechose lors de la dernière requête';
$this->_helper->FlashMessenger($message);
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.
Le gestionnaire d'aide (Broker)
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 de 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.
En interne, le gestionnaire d'aide utilise
une instance de PluginLoaderpour
conserver les chemins. Vous pouvez récupérer le PluginLoader en utilisant la méthode
statique getPluginLoader(), ou alternativement, injecter une instance
personnalisée de PluginLoader en utilisant setPluginLoader().
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')
}
Aides d'action intégrées
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.
ActionStack
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.
Note: Invoquer l'aide ActionStack initialise le plugin ActionStack
L'appel de l'aide ActionStack enregistre implicitement le plugin
ActionStack - ce qui veut dire que vous n'avez pas besoin
d'enregistrer explicitement le plugin ActionStack pour utiliser
cette fonctionnalité.
Example #1 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',
// Ajoute un appel à /bar/bat
// (BarController::batAction())
$this->_helper->actionStack('bat', 'bar');
}
}
Example #2 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();
// sans régler le contrôleur ou le module,
// utilise les valeurs courantes
$request->setActionName('baz')
-> setParams(array('bar' => 'baz'));
$this->_helper->actionStack($request);
// Ajoute un appel à /bar/bat
// (BarController::batAction())
$request = clone $this->getRequest();
// sans régler le module, utilise la valeur courante
$request->setActionName('bat')
->setControllerName('bar');
$this->_helper->actionStack($request);
}
}
AutoComplete
Beaucoup de librairies javascript AJAX propose une fonctionnalité dite
d'auto-complétion. Une liste de résultats possibles est chargée 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 (avec chaque membre étant un tableau associatif de métadonnées
utilisées pour créer la liste de sélection), 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 par
prepareAutoCompletion().
-
encodeJson($data, $keepLayouts = false) va encoder les
données en JSON. Cette méthode est appelées par
prepareAutoCompletion().
-
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 utilisée).
-
sendAutoCompletion($data, $keepLayouts = false) Va appeler
prepareAutoCompletion(), 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
$sendNow va déterminer si c'est
sendAutoCompletion() ou
prepareAutoCompletion(), qui doit être appelée.
Actuellement, AutoComplete supporte les librairies
AJAX Dojo et Scriptaculous.
AutoCompletion avec Dojo
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 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);
Example #3 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 complète pour la création
de javascript OO, un peu comme 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')
'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', ''));
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
:
<?php // configuration de l'entrepôt de données : ?>
<div dojoType="custom.TestNameReadStore" jsId="testStore"
url="<?php echo $this->baseUrl() ?>/unit-test/autocomplete/format/ajax"
requestMethod="get"></div>
<?php // rendu du formulaire : ?>
<?php echo $this-> form ?>
<?php // configuration des CSS de Dojo dans le head HTML : ?>
<?php $this->headStyle()->captureStart() ?>
@import "<?php echo $this->baseUrl()
?>/javascript/dijit/themes/tundra/tundra.css";
@import "<?php echo $this->baseUrl() ?>/javascript/dojo/resources/dojo.css";
<?php $this->headStyle()->captureEnd() ?>
<?php // configuration de javascript pour charger
// les librairies Dojo dans le head HTML : ?>
<?php $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");
<?php $this->headScript()->captureEnd() ?>
Notez les appels aux aides de vue comme headStyle et headScript ; celles-ci
sont des emplacements réservés, que nous pouvons ensuite utiliser pour effectuer
le rendu dans la section "head" du HTML de votre script de
layout.
Nous pouvons dès lors faire fonctionner l'auto-complétion Dojo.
AutoCompletion avec Scriptaculous
» 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".
ContextSwitch et AjaxContext
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.
-
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 :
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:
ContextSwitch vous permet d'écrire des contextes, ceux-ci spécifient le
suffixe de vue qui change, les en-têtes de réponse à modifier, et les fonctions de
rappel éventuelles.
Contextes inclus par défaut
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 éteigant le paramètre de
sérialisation JSON :
$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.
Créer ses propres contextes
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 et de 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 JSON 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
JSON est active, 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 que addContext().
-
addContexts(array $contexts) : Ajoute plusieurs
contextes d'un coup. Le tableau $contexts doit être un
tableau de paires contexte et 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 que addContexts().
-
hasContext($context) : retourne
TRUE si le contexte existe déjà,
FALSE sinon.
-
getContext($context) : retourne un contexte
par son nom. Le retour est un tableau qui a la même syntaxe que celui utilisé
par addContext().
-
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. Retourne TRUE si réussi,
FALSE si le contexte n'a pas été trouvé.
-
clearContexts() : Supprime tous les contextes.
Affecter des contextes par action
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(
'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. $context doit donc être
une chaîne, ou un tableau de chaînes.
Passer la valeur TRUE comme contexte marquera tous les
contextes comme disponibles pour cette action.
Une valeur vide pour $context dé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. $context doit être une chaîne ou
un tableau de chaînes.
-
addActionContexts(array $contexts) : Ajoute
plusieurs paires action et contexte en une fois. $contexts
doit être un tableau associatif action et contexte. Cette méthode proxie vers
addActionContext().
-
setActionContexts(array $contexts) : agit comme
addActionContexts(), mais écrase les paires
action et 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 et contexte.
-
removeActionContext($action, $context) : Supprime
un ou plusieurs contextes pour une action. $context doit ê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.
Initialiser le Context Switch
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 ; par exemple
vous pouvez vouloir seulement le contexte XML si la permutation de
contexte est active. Passez le alors à initContext() :
$contextSwitch->initContext('xml');
Fonctionnalités avancées
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é. $header
est le nom de l'en-tête et $content sa 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 $header spécifié pour le contexte existe déjà,
une exception sera alors levée.
-
setHeader($context, $header, $content) :
setHeader() agit comme
addHeader(), 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 vers
addHeader().$headers est un
tableau de paires header => contexte.
-
setHeaders($context, array $headers.) : comme
addHeaders(), sauf que cette méthode proxie vers
setHeader(), 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. Retourne NULL
si 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. Le déclencheur
peut être soit "init" ou "post" (la fonction de rappel sera appelée soit à
l'initialisation du contexte, ou à la fin, en postDispatch).
$callback doit être un nom de fonction PHP
valide.
-
setCallbacks($context, array $callbacks) :
affecte plusieurs fonctions de rappel pour un contexte.
$callbacks doit être un tableau de paires trigger et
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 et 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 valeur
FALSE à setAutoDisableLayout().
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 retourne
NULL si aucune permutation de contexte a été détectée,
ou si elle est appelée avant initContext().
Fonctionnalité AjaxContext
L'aide AjaxContext étend l'aide de permutation de contexte
ContextSwitch, donc toutes les fonctionnalités de
ContextSwitch 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 ou HTTP.
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 de contexte 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.
Example #4 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
"X-Requested-With: XmlHttpRequest", ce qui est en général le cas.
FlashMessenger
Introduction
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_Sessionpour
plus de détails sur son utilisation.)
Exemple d'utilisation basique
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();
}
}
JSON
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.
-
Optionnellement, un tableau d'options en second argument de
Zend_Json::encode(). Ce tableau d'options permet
l'activation des layouts et l'encodage en utilisant
Zend_Json_Expr.
$this->_helper-> json($data, array('enableJsonExprFinder' => true));
-
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);
}
}
Note: Conserver les Layouts
Si vous avez besoin des layouts séparés pour les réponses
JSON, 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
TRUE, les layouts resteront activées :
$this->_helper->json($data, true);
Optionnellement, vous pouvez fournir un tableau en tant que second paramètre.
Ce tableau peut conftenir une variété d'options, incluant l'option
keepLayouts :
$this->_helper-> json($data, array('keepLayouts' => true);
Note: Activer l'encodage en utilisant Zend_Json_Expr
Zend_Json::encode() permet l'encodage des
expressions JSON natives en utilisant des objets
Zend_Json_Expr. Cette option est désactivée par défaut. Pour
l'activer, fournissez la valeur booléenne TRUE à l'option
enableJsonExprFinder :
$this->_helper-> json($data, array('enableJsonExprFinder' => true);
Si vous souhaitez faire ceci, vous devez un tableau en
tant que second argument. Ceci vous permet aussi de combiner avec les autres
options, comme l'option keepLayouts. Toutes ces options sont
alors fournies à Zend_Json::encode().
$this->_helper-> json($data, array(
'enableJsonExprFinder' => true,
'keepLayouts' => true,
));
Redirector
Introduction
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 un
exit() juste après la redirection. Par défaut ceci vaut
TRUE.
-
setGotoSimple() peut être utilisée pour paramétrer l'URL par
défaut à utiliser si aucune n'est fournie à gotoSimple(). Elle
utilise les API de
Zend_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 avec
setGotoUrl(), gotoUrl(), ou
gotoUrlAndExit().
-
setUseAbsoluteUri() peut être utilisée pour forcer le
Redirector à 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() utilise setGotoSimple() (API
de type _forward() ) pour construire une URL et réaliser une
redirection.
-
gotoRoute() utilise setGotoRoute()
(assemblage de route ) pour construire une URL et réaliser une
redirection.
-
gotoUrl() utilise setGotoUrl() (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().
Exemples d'utilisation basique
Example #5 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
}
}
Example #6 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 */
$url = '/my-controller/my-action/param1/test/param2/test2';
$this->_redirector->gotoUrl($url);
return;
// jamais atteint puisque les paramètres par défaut
// sont à goto et exit
}
}
Example #7 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'));
}
}
Example #8 Utilisation de l'assemblage de la route avec gotoRoute()
L'exemple suivant utilise la méthode assemble() du
routeurpour 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'
);
}
}
ViewRenderer
Introduction
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 _forward(), redirect(), ou
render() manuellement, le rendu automatique sera annulé car
ViewRenderer saura que vous prenez la main.
Note:
Le ViewRenderer est activé par défaut dans le contrôleur
frontal. Pour le désactiver, utilisez le paramètre noViewRenderer
($front->setParam('noViewRenderer', true) ) ou retirez l'objet du
gestionnaire d'aides
( Zend_Controller_Action_HelperBroker::removeHelper('viewRenderer')).
Si vous voulez modifier un paramètre du ViewRenderer avant la
distribution du contrôleur frontal, il existe deux moyens :
API
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, mais
preDispatch() 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. $name doit être le nom de
l'action sans le suffixe (et sans le nom du contrôleur sauf si
noController a é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 , et
responseSegment .
-
setRender($action = null, $name = null, $noController =
false) vous permet de spécifier les paramètres
scriptAction , responseSegment , et
noController en 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:
setRender() et direct() ne rendent pas un
script de vue à proprement parler, mais elles notifient au
postDispatch() 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 :
-
:moduleDir représente le module courant (par convention le
dossier parent au dossier contrôleur).
-
:module pointe vers le module actuel.
-
:controller pointe vers le contrôleur actuel.
-
:action représente l'action actuellement traitée.
-
:suffix est 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 est
getViewBasePathSpec().
-
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.:suffix et
l'autre accesseur est getViewScriptPathSpec().
-
setViewScriptPathNoControllerSpec($spec) Une fois dans le
base path, si noController est 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.:suffix et l'autre accesseur est
getViewScriptPathNoControllerSpec().
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,
ViewRenderer en 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
ViewRenderer de modifier ces valeurs dynamiquement.
-
setInflector($inflector, $reference) peut être utilisée pour
passer son propre inflecteur à ViewRenderer . Si
$reference est à TRUE, alors le suffixe, le
répertoire du module et la cible seront affectés en fonction des propriétés de
ViewRenderer .
Note: Règles de résolution par défaut
Le ViewRenderer utilise certaines règles par défaut pour
chercher ses scripts de vue, voyez plutôt :
-
:module : casseMélangée et motsEnNotationCamel qui
deviennent des mots séparés par des tirets, et en minuscules. "FooBarBaz"
devient "foo-bar-baz".
En interne, l'inflecteur utilise les filtres
Zend_Filter_Word_CamelCaseToDash et
Zend_Filter_StringToLower.
-
:controller : casseMélangée et motsEnNotationCamel qui
deviennent des mots séparés par des tirets; les tirets bas eux, se
transforment en séparateur de dossier et tout est passé en minuscules.
"FooBar" devient "foo-bar"; "FooBar_Admin" devient "foo-bar/admin".
En interne, l'inflecteur utilise les filtres
Zend_Filter_Word_CamelCaseToDash,
Zend_Filter_Word_UnderscoreToSeparator, et
Zend_Filter_StringToLower.
-
:action : casseMélangée et motsEnNotationCamel qui se
transforment en mots séparés par des tirets, minuscules. Les caractères non
alphanumériques deviennent des tirets. "fooBar" devient "foo-bar";
"foo-barBaz" devient "foo-bar-baz".
Pour ceci, l'inflecteur interne utilise les filtres
Zend_Filter_Word_CamelCaseToDash,
Zend_Filter_PregReplace, et
Zend_Filter_StringToLower.
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. ViewRenderer s'attend à un paramètre
$script représentant un chemin complet vers un script de vue,
telle que la méthode de la vue render() l'attend.
Note:
Une fois rendue, la vue utilise noRender pour éviter un
double rendu automatisé.
Note:
Par défaut, Zend_Controller_Action::renderScript()
est un proxy vers la méthode renderScript() de
ViewRenderer .
-
getViewScript($action, $vars) récupère le chemin du script
de vue en se basant sur les paramètres $action et $vars. $vars
peut contenir "moduleDir", "module", "controller", "action", et "suffix"),
sinon les valeurs de la requête actuelle seront utilisées.
getViewScript() utilisera viewScriptPathSpec ou
viewScriptPathNoControllerSpec selon le paramètre
noController .
Les délimiteurs apparaissant dans les modules, contrôleurs ou actions seront
remplacés par des tirets ("-"). Ainsi pour un un contrôleur
"foo.bar" et une action "baz:bat", il
résultera un chemin de vue "foo-bar/baz-bat.phtml".
Note:
Par défaut Zend_Controller_Action::getViewScript()
est un proxy vers la méthode getViewScript() de
ViewRenderer .
-
render($action, $name, $noController) a beaucoup de
responsabilités : d'abord, elle vérifie si $name ou
$noController lui ont été passés, si c'est le cas, elle configure
correctement les paramètres responseSegment et
noController dans le ViewRenderer. Elle passe ensuite
$action, si spécifié, à getViewScript(). Enfin, elle
passe le script de vue calculé à renderScript().
Note:
Attention aux effets secondaires avec render() : les
valeurs segment de réponse, et noController vont persister
dans l'objet ViewRenderer. De plus, noRender() va être
appelée.
Note:
Par défaut, Zend_Controller_Action::render()
est un proxy vers render() de ViewRenderer .
-
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 $action et $vars à
getScriptPath(), pour en déduire un chemin qu'elle envoie alors
avec $name à renderScript().
Exemples
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 distribution
public function bazAction()
{
$this->_forward('index');
}
// Ne rend rien, une redirection est demandée
public function batAction()
{
$this->_redirect('/index');
}
}
Note:
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 distributeur s'attend à ce qu'ils soient séparés par des caractères bien
définis, dans l'URL. Le ViewRenderer les transforme alors en '/' pour
les chemins, ou tirets '-' pour les mots. Ainsi, un appel à
/foo.bar/baz.bat distribuera
FooBarController::bazBatAction() dans FooBarController.php, et ceci
rendra foo-bar/baz-bat.phtml . Un appel à /bar_baz/baz-bat
distribuera vers Bar_BazController::bazBatAction() dans
Bar/BazController.php (notez la séparation du chemin), et rend
bar/baz/baz-bat.phtml .
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 distribué
devient Bar_BazController, dans
Bar/BazController.php .
Example #10 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 setNeverRender()), pour désactiver totalement le rendu
automatique de vue vous fera perdre un des avantages majeur de
ViewRenderer .
Example #11 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 distribution. 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...
}
}
Example #12 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'2chappement 'htmlspecialchars'
$view = $this->_helper->viewRenderer->view;
$view->setEscape('htmlspecialchars');
}
}
Utilisation avancée
Example #13 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);
Example #14 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
}
}
Écrire vos propres aides
Les aides d'action étendent
Zend_Controller_Action_Helper_Abstract, une classe abstraite qui
fournit l'interface basique et les fonctionnalités requises par le gestionnaire
d'aides. Ceci inclue les méthodes suivantes :
-
setActionController() est utilisée pour paramétrer le
contrôleur d'action courant.
-
init(), déclenchée par le gestionnaire d'aides à
l'instanciation, peut être utilisée pour déclencher l'initialisation dans
l'aide ; ceci peut être pratique pour remettre dans l'état initial quand de
multiples contrôleurs utilisent la même aide dans des actions
enchaînées.
-
preDispatch() est déclenchée avant la distribution d'une
action.
-
postDispatch() est déclenchée quand une action a été
distribuée - même si un plugin preDispatch() a évité l'action.
Principalement utile pour le nettoyage.
-
getRequest() récupère l'objet de requête courant.
-
getResponse() récupère l'objet de réponse courant.
-
getName() récupère le nom de l'aide. Elle récupère la
portion du nom de la classe qui suit le dernier tiret bas ("_"), ou le nom de
la classe entier sinon. Pour exemple, si la classe est nommée
Zend_Controller_Action_Helper_Redirector, elle retourne
Redirector ; une classe nommée FooMessage
retournera FooMessage .
Vous pouvez optionnellement inclure une méthode direct() dans votre
classe d'aide. Si définie, ceci vous permet de traiter l'aide comme une méthode du
gestionnaire, dans le but de faciliter un usage unique de l'aide. Pour exemple, l'aide
Redirectordéfinit
direct() comme un alias de goto(), vous permettant d'utiliser
l'aide comme ceci :
// Redirige vers /blog/view/item/id/42
$this->_helper-> redirector('item', 'view', 'blog', array('id' => 42));
En interne, la méthode __call() du gestionnaire d'aides cherche une
aide nommée redirector , puis vérifie si cette aide possède une méthode
direct(), et enfin appelle cette méthode avec les arguments
fournis.
Une fois que vous avez créé vos propres classes d'aide, vous pouvez en fournir
l'accès comme décrit dans les sections ci-dessus.
|
|