Raccourcis : Contenu - rubriques - sous rubriques
EN FR

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, = et assetsRevision)

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 ou escxml : {$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}.

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.