Piste : • creation-action
Table des matières
Un peu de théorie ¶
Une action est un élément fondamental du framework. Tout affichage, tout traitement de formulaire, tout appel de service web est une action.
Une action est appelée dans le cadre d'une requête d'un type précis et génère une réponse spécifique dans un format spécifique, qui peut être lié au type de requête en question.
Il existe plusieurs types de requêtes, notament le type que l'on nomme dans Jelix, “classic”, pour lequel une action peut fournir une réponse dans un format quelconque : HTML, XML, etc. C'est pour ce type de requête que vous définirez le plus souvent des actions. En général, ce type de requête fournit ses paramètres dans l'url ou dans le corps de la requête HTTP (méthode POST).
Vous avez aussi des types de requêtes plus spécifiques, comme par exemple le type xmlrpc (utilisée dans le cadre d'un service web). En XML-RPC, les données en entrée ne sont pas des paramètres dans une url, mais sont stockées dans un contenu XML. Comme le veut le protocole XML-RPC, une action définie pour ce type de requête doit fournir obligatoirement une réponse au format XML-RPC.
En connaissant le type de requête traitée et l'action, Jelix connaît ainsi le type de la réponse à générer, et donc contrôle plus ou moins la génération de la réponse. Ainsi, même en cas d'erreur (une exception ou autre) survenant pendant le traitement de l'action, le format de sortie sera toujours celui attendu. Un client qui appelle un service web en XML-RPC, aura donc quoi qu'il arrive une réponse au format XML-RPC. Cela apporte une certaine robustesse à l'application.
Voici un schéma simplifié du déroulement d'une action :
- Jelix reçoit une requête HTTP. Il instancie un objet jRequest qui contient les données de la requête, et instancie le contrôleur qui correspond à l'action.
- La méthode du contrôleur correspondante à l'action est exécutée. La méthode récupère les paramètres de requête pour déterminer les traitements à suivre.
- Le contrôleur exécute les traitements métiers et récupère éventuellement des résultats qui seront utilisés pour l'affichage
- Le contrôleur instancie un objet de type jResponse auquel il assignera les données à afficher, initialisera les templates etc.
- Jelix récupère cet objet jResponse, invoque la génération du document en sortie et envoi ce dernier au navigateur.
Implémentation d'une action ¶
Les actions sont implémentées dans ce qu'on appelle des contrôleurs. Les
contrôleurs sont des classes contenant des méthodes pour chaque action.
Les contrôleurs sont stockés dans des fichiers controllers/nom_controleur.type_requete.php
.
En général il y a une méthode index()
pour l'action par défaut.
Modifions donc cette action par défaut. Pour cela ouvrons le fichier
module/news/controllers/default.classic.php
. Vous devez avoir ce contenu :
class defaultCtrl extends jController { function index () { $rep = $this->getResponse('html'); return $rep; } }
Vous remarquerez qu'il y a certaines conventions de nommage. Les classes contrôleurs ont un nom suffixé par “Ctrl”. Ce qui précède le suffixe, “default”, est le nom du contrôleur, que vous indiquerez dans le paramètre action, et c'est aussi le préfixe du nom du fichier *.classic.php.
Objet réponse ¶
Dans la méthode index()
du contrôleur, on récupère dans la variable
$rep une réponse de type “html”. Vous obtenez en fait un objet de
classe jResponseHtml
, dérivant de la classe jResponse
.
Vous verrez plus tard qu'il existe d'autres types de réponses et que vous pouvez développer vos propres objets réponse.
L'objet jResponseHtml
s'occupe de générer une réponse en HTML
(donc une page en HTML). Il génère automatiquement la partie <head> du HTML,
à partir de certaines de ses propriétés. On peut ainsi spécifier le titre de
la page, les feuilles de styles, les script javascript à lier etc. Par exemple,
pour indique le titre de la page :
$rep->title = 'Dernières actualités';
Et le navigateur recevra :
<head> <title>Dernières actualités</title> </head>
Tout le corps de la page, c'est à dire le contenu de la balise html <body>
,
doit être généré par vous même, via éventuellement le moteur de template de
Jelix : jTpl.
jResponseHtml
instancie en standard un moteur de template placé dans la
propriété body
. Le nom du fichier template est à placer dans la propriété
bodyTpl
.
Un objet réponse personnalisé ¶
En théorie donc, dans chaque action, vous devez indiquer à l'objet réponse HTML le titre, les feuilles de styles, le template principal etc. Si c'est la même chose à faire dans chaque action (ce qui est bien souvent le cas puisqu'en général les pages d'un même sites ont le même aspect, le même bandeau, menu etc), ça risque bien de devenir rébarbatif.
Pourquoi donc n'aurions nous pas un objet réponse html qui définit lui même ces propriétés, et qu'on récupérerait dans chaque action et en lui indiquant juste ce qui est spécifique à la page affichée ?
C'est en fait ce qui se passe dans une application créée avec create-jelix-app
.
Dans le répertoire app/responses/
, vous avez une classe myHtmlResponse
déjà créée, qui hérite de jResponseHtml
. Et qui défini certaines choses
par défaut:
class myHtmlResponse extends jResponseHtml { public $bodyTpl = 'jelix~defaultmain'; function __construct() { parent::__construct(); // Include your common CSS and JS files here } protected function doAfterActions() { // Include all process in common for all actions, like the settings of the // main template, the settings of the response etc.. $this->body->assignIfNone('MAIN','<p>no content</p>'); } }
On voit que le template par défaut des pages est le template “jelix~defaultmain”
(qui correspond au fichier lib/jelix/core-modules/jelix/templates/defaultmain.tpl
).
Cette classe myHtmlResponse
est déclarée dans la configuration comme
correspondant au type de réponse “html”. Ceci est spécifié dans app/system/mainconfig.ini.php
:
[responses] html=myHtmlResponse
Quand on fait donc $this->getResponse('html')
dans un contrôleur, nous
obtenons alors un objet myHtmlResponse
au lieu de jResponseHtml
(comme c'est le cas par défaut si on ne passe pas par createapp).
À propos de “jelix~defaultmain”, il n'est pas besoin de mettre le suffixe “.tpl” du nom du fichier, car il s'agit en fait d'un sélecteur Jelix. Un sélecteur est une chaîne, permettant de désigner facilement une ressource du projet, indépendement de son emplacement physique.
Un sélecteur comporte un nom de module et un nom de ressource séparés par le
caractère “~”, comme ceci : nom_module~nom_ressource
. La partie “nom_module~”
est facultative quand il s'agit du module courant. Le nom de la ressource n'est
pas forcément un nom de fichier, même si la plupart du temps elle désigne un
fichier. L'objet qui utilise le sélecteur
(ici jTpl) sait comment
récupérer le fichier correspondant au sélecteur. Vous verrez que les sélecteurs
sont abondamment utilisés, et permettent une certaine souplesse et une
indépendance vis à vis des chemins de fichiers physiques.
Premier affichage ¶
Voyons maintenant ce que génère cette réponse avec le template “jelix~defaultmain”, avant même que l'on ait à coder quoique ce soit.
Nous n'allons pas configurer un serveur web nginx ou apache, mais utiliser, pour la démonstration, le serveur web de php.
cd actu.org php -S localhost:8080 -t www
Tapons l'adresse suivante dans le navigateur : http://localhost:8080/index.php/news/default/index
“news” est le nom du module, “default” le nom du contrôleur, et “index” le
nom de la méthode dans le contrôleur. “default” et “index” étant des noms par
défaut pour Jelix, vous pouvez, pour cette action, taper http://localhost:8080/index.php/news/.
Ou encore, comme nous avons indiqué --default-module
à la création de l'application,
vous pouvez même juste indiquer http://localhost:8080.
Si il n'y a pas d'erreur, vous avez cette page :
Welcome in your new jelix application no content
Créer un template général ¶
Nous avons donc un template principal (“jelix~defaultmain”) pour toutes les pages.
Comme vous le voyez à l'affichage, ce n'est pas forcément ce que vous voulez.
Créer donc un nouveau template général, que vous mettrez dans
modules/news/templates/main.tpl
par exemple:
<h1>Actu.org: toute l'actu</h1> <div id="maincontent"> {$MAIN} </div>
Comme il a été dit auparavant, le contenu du template sera le contenu de la
balise <body>
. C'est pourquoi vous n'avez pas à mettre les balises
standard <html>
, <head>
, etc… Juste le contenu de la page.
{$MAIN}
affiche une variable de template nommée $MAIN. Dans chaque action,
vous devrez indiquer le contenu de cette variable, qui sera dans le cadre de
notre application, le contenu spécifique de la page que l'on veut afficher.
Spécifions maintenant ce template à notre réponse personnalisée dans
responses/myhtmlresponse.class.php
:
class myHtmlResponse extends jResponseHtml { public $bodyTpl = 'news~main'; ....
Si vous rafraîchissez http://localhost:8080/news/, vous devriez voir votre nouveau template.
Template de contenu spécifique ¶
Pour notre action principale, nous allons définir un template, dont le contenu sera assigné à la variable $MAIN du template principal (ce qui vous fera donc deux templates).
Créez un fichier listenews.tpl dans le répertoire templates du module. Et mettez y ce contenu :
<h2>Dernières actualités</h2> <p>Ouverture prochaine de cette rubrique.</p>
Utilisation du template dans l'action ¶
Voyons maintenant comment cela se concrétise dans le contrôleur :
class defaultCtrl extends jController { function index () { $rep = $this->getResponse('html'); // on définit un titre de page $rep->title = 'Dernières actualités'; // creation d'un objet template pour le contenu spécifique $tpl = new jTpl(); // assignation du resultat du template listenews à la variable $MAIN $rep->body->assign('MAIN', $tpl->fetch('listenews')); return $rep; } }
Rafraichissez la page dans votre navigateur. Vous devriez avoir:
Actu.org: toute l'actu Dernières actualités Ouverture prochaine de cette rubrique.
ou plus exactement le code HTML suivant :
<h1>Actu.org: toute l'actu</h1> <div id="maincontent"> <h2>Dernières actualités</h2> <p>Ouverture prochaine de cette rubrique.</p> </div>
Problème d'affichage des caractères accentués ¶
Si les caractères accentués s'affichent mal dans votre navigateur, c'est que l'édition de vos fichiers ne s'est pas faite avec le même encodage que celui indiqué dans la configuration de Jelix (qui est par défaut UTF-8). Donc :
- soit vous modifiez la configuration de votre éditeur préféré pour qu'il édite en UTF-8, et il faut alors convertir vos scripts/templates existants pour UTF-8 (ou les réécrire)
- soit vous modifiez le fichier
app/system/mainconfig.ini.php
en changeant la propriété charset (en mettant ISO-8859-1 par exemple). Toutefois, nous vous recommandons de rester en UTF-8, ceci étant le charset universel et le plus adopté sur le web aujourd'hui.