Section: Définir une réponse générale personnalisée
« Générer un sitemap | ^ Générer du contenu avec les vues |
− Table des matières
Il est fort probable que vous ayez dans la plupart de vos actions, à initialiser la même feuille de style, les mêmes zones de menus, et autres traitements de personnalisation de la réponse. Plutôt que de répéter toutes ces opérations dans chaque contrôleur, vous allez créer un objet response qui fait le travail commun à toutes les actions.
Si vous voulez réaliser des modules réutilisables, cette façon de faire est d'autant plus intéressante puisqu'alors tout ce qui ne concerne pas le module est réalisé à l'extérieur de ce module. Il est donc plus indépendant de l'application, contrairement au cas où il gère lui même dans ses actions les parties communes des pages du site (bandeau etc...).
Dans cette section, nous allons parler principalement de la création d'un objet réponse héritant d'un autre objet réponse "évolué" existant. Si vous voulez créer un objet réponse pour un nouveau type de format, voir le chapitre sur la génération d'un contenu dans un format spécifique.
Créer un objet réponse à partir d'une classe existante ¶
Vos propres classes de réponses peuvent hériter de jResponseHtml
par
exemple (mais ça pourrait bien sûr être une autre classe jResponse*
fournie
par Jelix). D'ailleurs, par défaut, quand vous créez une application avec
jelix-scripts, un tel objet est déjà créé, myHtmlResponse
, qui hérite de
jResponseHtml
et est stocké dans le répertoire app/responses/
de l'application.
Dans cette classe, vous pouvez alors :
- surcharger le constructeur pour réaliser des choses qui seront faites
lorsque vous ferez le
getResponse()
dans votre contrôleur - surcharger la méthode
doAfterActions()
. Notez que cette méthode n'existe que pourjResponseHtml
. Elle sera appelée après votre action, et juste avant l'affichage définitif.
Voyons plus précisément comment ça se gère globalement. Vous avez donc vos pages
HTML, qui contiennent la partie <head>
et la partie <body>
:
Vous aurez un template principal qui s'occupe de générer l'ensemble du contenu
de <body>
, et ce template va être déclaré au niveau de votre propre objet
réponse. Voici par exemple votre objet app/responses/myHtmlResponse.class.php
:
require_once (JELIX_LIB_CORE_PATH.'response/jResponseHtml.class.php');
class myHtmlResponse extends jResponseHtml {
public $bodyTpl = 'myapp~main';
protected function doAfterActions(){
}
}
Votre page est en général découpée en zones :
Ainsi le template pourrait ressembler à ceci
<div id="header"> ... {$date} </div>
<div id="sidebar-left"> {$A} {$B} {$C} </div>
<div id="sidebar-right"> {$D} </div>
<div id="main-content"> {$MAIN} </div>
<div id="footer"> ...</div>
Ces zones A, B, C, D et MAIN peuvent être générées par des sous-templates ou des
objets jZone
, matérialisés ici par des parties distinctes :
En particulier, la partie MAIN sera générée par les actions, en utilisant un template, une zone ou autre.
Ainsi l'objet réponse pourra s'occuper par exemple de la partie A (si celle-ci est commune à toutes les pages), et les autres zones seront remplies à loisir par les actions. Dans l'objet réponse on aura donc :
require_once (JELIX_LIB_CORE_PATH.'response/jResponseHtml.class.php');
class myHtmlResponse extends jResponseHtml {
public $bodyTpl = 'myapp~main';
protected function doAfterActions(){
// toutes les pages auront une zone de login affichée
$this->body->assignZone("A", "auth~login");
// et au cas où rien n'est défini pour B,C,D et MAIN, on met du contenu
// par défaut
$this->body->assignIfNone('B','');
$this->body->assignIfNone('C','');
$this->body->assignIfNone('D','');
$this->body->assignIfNone('MAIN','<p>No content</p>');
// on indique les autres variables
$this->body->assign('date', date('Y-m-d'));
}
}
Dans les actions (contrôleurs), on fera donc des choses comme :
function mon_action() {
$rep = $this->getResponse('html');
// on indique du contenu pour B
$rep->body->assign('B','<h2>Hello !</h2>');
// on indique du contenu pour D
$rep->body->assignZone('D', 'ma_sidebar');
// Dans cette action, pas de contenu pour C,
// donc on ne fait rien pour C
// on s'occupe maintenant de la partie principale
// qui a son propre template
$tplMain = new jtpl();
$tplMain->assign(...);
$rep->body->assign('MAIN', $tplMain->fetch('contenu_mon_action'));
return $rep;
}
Bien sûr, la réponse peut définir aussi autre chose que le template : feuille de styles et cie. Ce qui évite de le faire dans les actions. Exemple, en surchargeant le constructeur :
class myHtmlResponse extends jResponseHtml {
public $bodyTpl = 'myapp~main';
// traitement executé AVANT les actions
public function __construct() {
parent::__construct();
$this->addCSSLink('design/screen.css');
}
// traitement executé APRES les actions
protected function doAfterActions(){
$this->title .= ($this->title !=''?' - ':'').' My App';
// toutes les pages auront une zone de login affichée
$this->body->assignZone("A", "auth~login");
// et au cas où rien n'est défini pour B,C,D et MAIN, on met du contenu
// par défaut
$this->body->assignIfNone('B','');
$this->body->assignIfNone('C','');
$this->body->assignIfNone('D','');
$this->body->assignIfNone('MAIN','<p>No content</p>');
// on indique les autres variables
$this->body->assign('date', date('Y-m-d'));
}
}
- *Note** : vous ne devez pas assigner des zones dans le constructeur de la réponse, surtout si la zone en question veut ajouter des feuilles de style ou faire d'autres modifications sur l'objet réponse. En effet, l'objet réponse n'est pas encore déclaré dans l'environnement jelix, et donc la zone ne pourra y accéder.
Déclaration de l'objet réponse ¶
Cet objet réponse est déclaré comme ceci dans la configuration :
[responses]
html=myHtmlResponse
Jelix cherchera la classe indiquée dans le répertoire app/responses/
de l'application.
Si cette classe se trouve dans le répertoire responses/
d'un module ("main"
par exemple), il faut l'indiquer comme un sélecteur :
[responses]
html="main~myHtmlResponse"
Ou encore, si votre classe a un namespace qui est auto-chargeable :
[responses]
html="\My\Html\Response\Class"
Toutes les actions qui feront alors appel à la réponse "html", fourniront un
objet myHtmlResponse
, et donc une page avec un formulaire de login généré
par la zone 'auth~login', un contenu par défaut pour les variables de templates
MAIN, A, B etc (si elles n'ont pas été définies par l'action).
Astuces utiles ¶
Lorsque vous définissez une réponse personnalisée, il peut être utile de récupérer certaines valeurs de votre application, comme
- le theme:
jApp::config()->theme
- les paramètres de la requête:
jApp::coord()->request->getParam(..)
Ci-dessous un exemple :
public function __construct() {
parent::__construct();
$theme = jApp::urlBasePath().'themes/'.jApp::config()->theme.'/' ;
$this->addCSSLink($theme.'css/screen.css');
}
protected function doAfterActions(){
$this->title .= ($this->title !=''?' - ':'').' My App';
$param = jApp::coord()->request->getParam('paramSommaire')
// toutes les pages auront une zone de login affichée
$this->body->assignZone("A", "auth~login", array( 'paramSommaire' => $param ) );
// et au cas où rien n'est défini pour B,C,D et MAIN, on met du contenu
// par défaut
$this->body->assignIfNone('B','');
$this->body->assignIfNone('C','');
$this->body->assignIfNone('D','');
$this->body->assignIfNone('MAIN','<p>No content</p>');
// on indique les autres variables
$this->body->assign('date', date('Y-m-d'));
}
Définir plusieurs réponses ¶
Notez que vous pouvez définir plusieurs réponses html, dans le cas où votre site comporte plusieurs pages type. Par exemple :
[responses]
html = myHtmlResponse
html2 = myOtherHtmlResponse
admin = adminHtmlresponse
Il suffira alors dans les actions d'indiquer le bon code pour indiquer le type de réponse :
$repHTML = $this->getResponse('html');
// ou
$repHTML2 = $this->getResponse('html2');
// ou
$repAdmin = $this->getResponse('admin');
Utiliser ponctuellement une réponse d'origine ¶
Si dans une action, vous voulez absolument utiliser la classe d'origine fournie
par Jelix, et non celle qui redéfinit un type de réponse, vous pouvez alors
l'indiquer en indiquant true
en deuxième paramètre de getResponse()
:
$rep = $this->getResponse('html', true);
$rep contiendra un objet de type jResponseHtml
, et non myHtmlResponse
.