- ^ Composants de jelix
- jTpl : le moteur de templates
- jZone : découper vos pages en zones
- jDao : mapping objet relationnel
- Formulaires classiques
- jForms : des formulaires automatiques
- jDb : accéder à une base de données SQL
- jKvDb : accéder à une base de type key/value
- jUrl : des URLs automatiques
- jAuth : système d'authentification
- jAcl2 : système de droits
- jLocale: internationaliser votre application
- jEvents : communication inter-module
Chapitre: jTpl : le moteur de templates
^ Composants de jelix | jZone : découper vos pages en zones » |
− Table des matières
Jelix inclut son propre moteur de template jTpl, basé sur le moteur de template
Castor. Les templates sont des fichiers
portant l'extension ".tpl" et se trouvant dans le répertoire templates
des
modules.
L'objet jTpl ¶
L'objet jTpl
sert à générer le contenu indiqué dans un fichier template, à
partir des données que vous lui fournissez, et en suivant les instructions
contenues dans le template.
Certains objets jResponse
ou jZone
instancient pour vous un objet
jTpl
. Par exemple, la propriété body
de l'objet jResponseHtml
est un objet jTpl, de même que la propriété _tpl
de jZone
.
Dans d'autres circonstances, vous aurez à faire :
$tpl = new jTpl();
Voici les méthodes les plus importantes à connaître.
assign ¶
$tpl->assign($nom, $valeur);
Cette méthode vous permet de créer une variable de template. Une variable de template n'est accessible qu'au niveau du template. C'est avec cette méthode que vous pouvez donc passer des données (valeurs statiques, objets, itérateurs, etc..) au template pour vous en servir à générer du contenu.
Vous pouvez également créer ou modifier une variable directement dans le fichier tpl en utilisant.
{assign $nom = $valeur}
- *Important** : le nom de la variable de template doit respecter les conventions de nommage des noms de variables PHP. Par exemple, le nom ne doit pas contenir de tiret ou d'autres signes de ponctuations. Il ne doit contenir que des lettres avec éventuellement des chiffres et le caractère souligné (_).
assignByRef ¶
Idem que assign
, à ceci prés que la valeur est passée par référence, ce
qui évite une copie et donc une consommation de la mémoire excessive. À utiliser
par exemple si vous passez des tableaux volumineux.
assignIfNone ¶
Idem que assign
, mais la valeur est assignée à la variable uniquement si
celle-ci n'existe pas.
assignZone ¶
$tpl->assignZone($name, $zoneSelector, $params);
Le paramètre $params est facultatif. Cette méthode est un raccourci de :
$tpl->assign($name, jZone::get($zoneSelector, $params));
assignZoneIfNone ¶
Idem que assignZone
, mais la valeur est assignée à la variable uniquement
si celle-ci n'existe pas.
get ¶
Si vous voulez récupérer la valeur d'une variable de template déjà initialisée, vous pouvez utiliser cette méthode.
$value = $tpl->get('foo');
Récupération du contenu ¶
Une fois que les variables sont initialisées, vous pouvez appeler la méthode
fetch
pour générer le contenu du template et le récupérer. Vous donnerez à
cette méthode le sélecteur du fichier de template.
$contenu = $tpl->fetch('mymodule~mytemplate');
L'appel de cette méthode n'est indispensable que dans le cas où vous avez
instancié vous même l'objet jTpl
.
Il existe une autre méthode, mais que vous n'appellerez certainement jamais
puisque les objets jResponse
le font à votre place : display
.
$tpl->display('mymodule~mytemplate');
Le contenu du template est évalué et affiché directement.
Les fichiers templates ¶
Un fichier de template contient du HTML, du XML ou ce que vous voulez qui soit en rapport avec le type de la réponse. Il contient aussi des instructions pour incorporer des valeurs que vous aurez fournies, des instructions pour générer répétitivement des portions de HTML etc.
La syntaxe utilisée dans jTpl
est à mi chemin entre celle utilisée dans le
moteur de template Smarty, et la syntaxe PHP. Le but étant d'avoir des templates
suffisamment lisibles, faciles à modifier en n'imposant pas une syntaxe trop
éloignée de PHP, tout en proposant des facilités que ne possède pas PHP et
propres à Jelix.
Il faut avoir en tête que la plupart des templates que vous ferez ne doivent pas
contenir de fichiers entiers. En particulier, pour les réponses HTML, vos
templates ne doivent contenir que ce qui se trouve entre les balises
<body>
et </body>
de votre page, le reste étant généré
automatiquement par jResponseHtml
.
Syntaxe des instructions ¶
Les instructions jTpl sont spécifiées entre accolades : {instruction....}
.
Si vous voulez inclure des accolades dans le source, sans que ce soit interprété
par jTpl, vous pouvez utiliser {ldelim}
pour {
, et {rdelim}
pour
}
. Si vous avez un bloc contenant plusieurs accolades (comme du code
javascript), vous pouvez aussi utiliser l'alternative avec {literal}
:
<script type="text/javascript">
{literal}
for(i=0;i<max;i++) {
if(foo){ ...}
}
{/literal}
</script>
Si vous voulez mettre des commentaires qui ne seront pas inclus dans le contenu
généré, utilisez {*...*}
<p>bla bla</p>
{* ceci est un commentaire *}
Vous pouvez étaler une instruction sur plusieurs lignes :
<div>
{zone
'foo~bar',
array(
'foo1'=>$foo1,
'foo2'=>$foo2)}
</div>
Expressions ¶
Une expression jTpl est identique à une expression PHP et renvoie, comme dans PHP, une valeur. Vous pouvez utiliser les opérateurs PHP classiques, les objets, etc... Vous utiliserez les expressions au niveau des arguments des instructions jtpl. On peut utiliser les variables de templates qu'on a passé à jTpl, comme des variables classiques en PHP. Voici un exemple d'expression simple :
$nom_variable_de_template
Une expression peut contenir aussi des sélecteurs de locale, en utilisant une syntaxe spécifique à jTpl. Ce type de sélecteur doit être placé entre "@". jTpl ira chercher la chaîne correspondante dans la langue courante :
@mon_module~cle.chaine.localisee@."fooo bar"
La chaîne correspondant à mon_module~cle.chaine.localisee
sera récupérée
et concaténée à "fooo bar"
.
À l'intérieur du nom de la clé, on peut indiquer un nom de variable de template. Cela permet ainsi de construire un nom de clé dynamiquement.
@mon_module~cle.chaine.$nom_variable_template.autre@."fooo bar"
si $nom_variable_template vaut "foo"
, alors la clé sera
"mon_module~cle.chaine.foo.autre"
. Cette expression est équivalente au
code php :
jLocale("on_module~cle.".$nom_variable_template.".autre")."fooo bar"
Affichage d'une expression, d'une variable ¶
Il faut mettre l'expression entre accolades. Elle doit commencer par un nom de variable ou par un sélecteur de locale :
{$mavariable}
{$mavariable * 3}
{$mavariable." - ".@mod~message.ok@}
{@modul~une.cle.de.locale@."-".$uneAutreVariable}
{@modul~une.cle.$dynamique@."-".$uneAutreVariable}
Ceci est équivalent en php à
<?php echo $mavariable; ?>
<?php echo $mavariable * 3; ?>
<?php echo $mavariable." - ".jLocale::get("mod~message.ok"); ?>
<?php echo jLocale::get("modul~une.cle.de.locale")."-".$uneAutreVariable; ?>
<?php echo jLocale::get("modul~une.cle.".$dynamique)."-".$uneAutreVariable; ?>
Pour les expressions plus complexes ne commençant pas par un nom de variable ou de locale, on peut utiliser le signe "=" :
{=$mavariable}
{=intval($mavariable) * 65}
Constantes prédéfinies ¶
Pour apporter une certaine facilité, des variables de templates prédéfinies ont été ajoutées :
- $j_basepath : contient le chemin url du répertoire de l'application (paramètre de configuration basePath)
- $j_jelixwww : contient le chemin url vers le contenu du répertoire
jelix-www
(paramètre de configuration jelixWWWPath) - $j_themepath : contient le chemin url vers le répertoire du thème courant
- $j_datenow : date courante (aaaa-mm-jj)
- $j_timenow : heure courante (hh:mm:ss)
- $j_locale : code de la locale courante (valeur de
jApp::config()->locale
) - $j_lang : code de la langue courante
- $j_country : code du pays courant
- j_assetsRevision : la valeur du paramètre de configuration
assetsRevision
- j_assetsRevisionParameter : la valeur du paramètre de configuration
assetsRevisionParameter
- j_assetsRevQueryUrl : la partie à ajouter aux paramètres url (concatenation de
assetsRevisionParameter
,=
etassetsRevision
)
Modificateurs ¶
Un modificateur est en fait une fonction qui va modifier le contenu qui va être affiché. Cela fonctionne comme dans smarty. On peut mettre plusieurs modificateurs à la suite :
{$unevariable|upper}
{$unevariable|upper|escxml}
{$uneUrl|escurl}
Ceci est en fait équivalent à :
<?php echo strtoupper($unevariable);?>
<?php echo htmlspecialchars(strtoupper($unevariable));?>
<?php echo rawurlencode($uneUrl);?>
Les modificateurs indiqués en exemple sont de simples alias à des fonctions existantes, mais vous pouvez créer vos propres modificateurs, pouvant accepter plusieurs arguments.
Les modificateurs existants et leur équivalent php :
- upper (strtoupper)
- lower (strtolower)
- escxml et eschtml (htmlspecialchars)
- strip_tags (strip_tags)
- escurl (rawurlencode)
- capitalize (ucwords)
- stripslashes (stripslashes)
- upperfirst (ucfirst)
D'autres sont fournis. Voir la liste sur la référence API.
Modificateur avec paramètres ¶
Il peut y avoir des modificateurs qui acceptent des paramètres. Vous devez mettre ceux-ci, séparés par des virgules (,) , après le nom du modificateur et deux-points (:).
Exemple : ici le modificateur jdatetime
, prenant deux paramètres de type chaîne :
<p>la date est {$myDate|jdatetime:'db_date','timestamp'}.</p>
Échapper du contenu ¶
Par défaut, le contenu des variables est inséré tel quel, sans modification. Ce n'est pas forcément
ce que vous voulez. En particulier, vous voudriez probablement échapper certains caractères
réservé au HTML, comme <
et >
, ainsi le navigateur ne les interpreterez pas comme étant des
déclaration d'élements HTML.
Donc vous pouvez échapper le contenu d'une variable :
- en utilisant les modificateurs
eschtml
ouescxml
:{$myvar|eschtml}
- ou en activant l'auto-échappement, en ajoutant un tag
{! autoescape !}
au début de votre template. Tout affichage de variables (avec un tag{$..}
) sera échappé.- Si il y a déjà un modificateur
eschtml
, le contenu ne sera pas échappé deux fois. - Si pour une variable particulière, vous ne voulez pas échapper son contenu
utilisez le modificateur
raw
:{$myHTMLcontent|raw}
.
- Si il y a déjà un modificateur
Les structures de contrôle ¶
Elles sont équivalentes à celle en PHP, excepté que les expressions ou conditions n'ont pas besoin d'être encadrés par des parenthèses.
if, else, elseif ¶
{if condition_1}
// code ici
{elseif condition_2}
// code ici
{else}
// code ici
{/if}
Notez aussi qu'il y a des plugins pour faire des "if" specifiques comme @@ifacl2
'un.droit'@@ pour tester un droit. Avec tout ces plugins en "if", vous pouvez
utiliser un else
.
while ¶
Boucle conditionnelle:
{while condition}
// code ici
{/while}
foreach ¶
Boucle sur un iterateur ou un tableau:
{foreach $iterateur_ou_tableau as $cle => $valeur}
// code ici
{/foreach}
for ¶
{for expression}
// code ici
{/for}
L'expression est bien sûr semblable à celle du "for" en PHP.
break ¶
Vous pouvez avoir l'équivalent d'un break
dans une boucle, en utilisant
{break}
:
{while condition}
...
{if ...} {break} {/if}
....
{/while}
Fonctions jTpl ¶
Ce sont des fonctions classiques mais appelables uniquement dans un template. Certaines sont disponibles en standard et vous pouvez en réaliser en créant un plugin de template. Leur syntaxe est :
{nom_fonction paramètres}
Les paramètres sont des expressions jTpl, donc similaires aux expressions PHP. Cependant, contrairement en PHP, il ne faut pas entourer les paramètres par des parenthèses.
Sachez que les fonctions, et en général la plupart des plugins de templates, sont attribués à un type de réponse particulier. Donc il existe des fonctions utilisables dans des templates pour les réponses HTML, mais pas dans les templates pour les réponses Text par exemple.
Fonctions et modificateurs personnalisés ¶
Si vous voulez avoir des fonctions ou modificateurs supplémentaires, vous pouvez réaliser des plugins de templates. Voir la documentation sur ce sujet. C'est assez simple à faire.
Une deuxième solution est de déclarer les modificateurs ou fonctions à la volée
au moteur de template. Vous avez pour cela deux méthodes
registerModifier()
et registerFunction()
. Vous leur indiquez le nom
"jtpl" du modificateur ou de la fonction, ainsi que le nom de la fonction php
qui sera executée par le template. Cette fonction doit accepter les même
arguments que pour une fonction de plugin de template.
Informations meta ¶
Il existe une balise assez spéciale : {meta}
. Elle n'influence pas
l'interprétation du template, ne génère aucun contenu, et **ne peut être
influencée par d'autres instructions de template** (la mettre dans un {if} par
exemple ne sert à rien, elle sera interprété quoi qu'il arrive). Cette balise
permet simplement de fournir des informations sur le template qui pourraient
être réutilisées par un programme utilisant le template.
{meta nom expression}
Exemple :
{meta auteur 'laurent'}
On peut en mettre plusieurs bien sûr. Ces informations sont récupérables via la
méthode meta()
de l'objet jTpl
:
$tpl = new jTpl();
$metas = $tpl->meta('le_fichier_template');
echo $metas['auteur']; // affiche 'laurent'
Note : si vous utilisez une variable dans l'expression dans un tag meta
,
cette variable doit être créée via la méthode assign()
de l'objet jtpl, et
non pas avec un tag jtpl comme {assign ...}
.
Informations meta avançées ¶
Des informations meta peuvent être traitées automatiquement via un plugin de template. Par exemple, il existe un plugin de meta permettant d'indiquer des informations pour une réponse HTML (feuille de style CSS, script JS, etc...). Leur syntaxe est :
{meta_//nom_plugin// nom expression}
Exemple :
{meta_html css '/styles/my.css'}
{meta_html js 'fooscript.js'}
{meta_html bodyattr array('onload'=>'alert("charge")')}
Bien sûr vous pouvez réaliser le vôtre.
Inclusion de templates dans un template ¶
Il y a des cas où vous voudriez partager du contenu de template entre plusieurs
templates. Pour ce faire, vous créerez un template contenant ce code commun, et
utiliserez la balise {include}
. Vous devez lui donner le sélecteur du
template à inclure en paramètre.
<div>
...
{include 'mymodule~sharedcontent'}
</div>
Toutes les variables déclarées dans l'objet jTpl
seront accessibles dans
le template inclus.
Si vous ne voulez pas que les variables soient propagées dans le template inclus,
vous utiliserez la balise {fetchtpl}
. Elle est particulièrement utile quand
vous voulez inclure un template recursivement.
<div>
...
{fetchtpl 'mymodule~sharedcontent'}
</div>
Avant d'utiliser la balise {include}
ou {fetchtpl}
, envisagez l'utilisation
d'une zone, car cela peut être une meilleure solution, d'autant plus
que son contenu peut être mis en cache.
Macros ¶
Dans un template, vous avez peut-être besoin de répeter un morceau de HTML sans utiliser de boucle. Une solution est d'inclure plusieurs fois même un sous-template. Mais pour des petits bouts de HTML, il est plus performant et moins complexe d'utiliser une macro.
Une macro est une partie d'un template déclaré avec le tag {macro}
. Une macro a un nom, et
fonctionne comme une fonction PHP.
Exemple d'une declaration de macro :
{macro 'myblock'}
<p>Ceci est un block, affichant la valeur de $val : {$val}</p>
{/macro}
Le nom est déclaré comme une chaîne PHP. Les variables ou autre syntax ne sont pas autorisés.
Les variables utilisées à l'intérieur d'une macro peuvent être des variables déclarées dans le template. Le scope est globale au template. Vous pouvez utiliser n'importe quel plugin, expressions, structures de contrôle...
Pour appeller une macro, utilisez {usemacro}
:
Ceci est mon morceau de HTML :
{usemacro 'myblock'}
...
Je peux afficher mon morceau de HTML encore une fois :
{usemacro 'myblock'}
Si $val
équiveaut à 'hello'
, le résultat sera :
Ceci est mon morceau de HTML :
<p>Ceci est un block, affichant la valeur de $val : hello</p>
...
Je peux afficher mon morceau de HTML encore une fois :
<p>Ceci est un block, affichant la valeur de $val : hello</p>
Vous pouvez déclarer des paramètres à la macro. Indiquez les comme pour une fonction PHP, et utilisez les à l'intérieur d'une macro comme toutes variables de template.
{* declaration de la macro *}
{macro 'myblock', $name, $result}
<p>C'est une macro avec parametres.<p>
<ul>
<li>name= {$name}</li>
<li>{if $result == true}c'est vert{else}c'est rouge{/if}</li>
</ul>
<p>Vous pouvez encore voir la valeur de $val : {$val}</p>
{/macro}
{* utilisation de la macro *}
{usemacro 'myblock', 'SuperGuppy', true}
Les paramètres déclarés ne sont pas utilisables en dehors de la macro. Si il y a une variable de template avec le même nom, la valeur de la variable de template sera remplacé par celle du paramètre à l'intérieur de la macro, mais gardera sa valeur originelle en dehors de la macro.
Les macros déclarées dans un sous-template peuvent être utilisées dans le template appelant.
Templates Virtuels ¶
Vous pouvez utiliser des templates qui ne sont pas dans des fichiers. Ce sont les templates virtuels. Typiquement, votre template doit être dans une chaîne.
Voici un exemple simple :
$template = ' hello
{$value}
world
{for $i=1;$i<=5;$i++}
{$i}
{/for}';
$tpl = new jTpl();
$tpl->assign('value', 'test');
$content = $tpl->fetchFromString($template, 'text');
Vous devez donc utiliser la méthode fetchFromString
, à laquelle vous
donnez une chaine contenant un template, et éventuellement le type de ce contenu
(text
, html
...).
Cela renverra le contenu généré à partir du template. Dans notre exemple,
$content
contiendra:
hello
test
world
1
2
3
4
5
Vous pouvez ensuite utiliser ce contenu pour l'injecter dans un autre template par exemple.
Templates localisées ¶
Dans un template, nous avons vu que nous pouvons utiliser {@truc.foo@}
pour
inclure des chaînes localisés. Cependant, il peut arriver qu'il y en ait beaucoup
dans un même template, pouvant rendre alors celui-ci pas très lisible, et
surtout plus lent à s'afficher.
Une solution existe : créer des templates pour chaque langue. Bien sûr, cela fait de la duplication de code, aussi, à vous de peser le pour et le contre : maintenance versus performance.
Pour faire un template pour chaque langue, créer des sous-repertoires dans le
repertoire de templates, et qui ont pour nom le code de la langue. Exemple, dans
un module: templates/fr_FR
, templates/en_US
etc.. Et placez y dans
chacun d'eux un exemplaire de votre template traduit.
Redéfinition de template ¶
Chaque module définit des templates qui lui sont propres, mais pour éviter d'avoir à retravailler sur les templates originaux du module lorsque ce dernier est réutilisé dans une autre application, il est possible d'appliquer d'autres templates afin de produire un nouvel affichage, sans toucher au contrôleur.
Pour cela Jelix utilise un système de thème, le thème par défaut étant stocké
dans app/themes/default/
, il est possible d'ajouter d'autres thèmes en
ajoutant simplement des répertoires dans app/themes
, par exemple
app/themes/mon_theme
.
Ainsi app/themes/mon_theme/mon_module/mon_template.tpl
redéfini le
template mon_template
du module mon_module
pour le thème mon_theme
.
Pour plus de détails, voir la page sur les thèmes.
En coulisse ¶
Les templates jTpl sont "compilés" sous forme de fichiers purs PHP, et stockés
dans un cache pour améliorer les performances. Vous pouvez donc voir
l'équivalence d'un de vos fichiers templates dans
temp/compiled/templates/modules/nom_module~nom_template.php
ou pour les templates redefinis dans les themes :
temp/compiled/templates/app/themes/nom_theme/nom_module~nom_template.php
.
Vous pouvez créer aussi des plugins de templates, pour ajouter vos propres "tags" dans la syntaxe jtpl. Voir /plugins/tpl.