Syntaxe

La syntaxe de Latte est née des besoins pratiques des webdesigners. Nous cherchions la syntaxe la plus accueillante possible, celle qui permet d'écrire élégamment des constructions qui relèvent autrement du casse-tête. En même temps, toutes les expressions s'écrivent exactement comme en PHP, si bien que vous n'avez pas de nouveau langage à apprendre. Vous mettez simplement à profit ce que vous savez déjà.

Ci-dessous se trouve un template minimal qui illustre plusieurs éléments de base : balises, n:attributs, commentaires et filtres.

{* ceci est un commentaire *}
<ul n:if=$items>                  {* n:if est un n:attribut *}
{foreach $items as $item}         {* balise représentant une boucle foreach *}
	<li>{$item|capitalize}</li>   {* balise affichant une variable avec un filtre *}
{/foreach}                        {* fin de la boucle *}
</ul>

Examinons de plus près ces éléments importants et la façon dont ils vous aident à créer un template épatant.

Balises

Un template contient des balises qui pilotent sa logique (par exemple les boucles foreach) ou affichent des expressions. Un unique délimiteur { ... } sert aux deux, si bien que vous n'avez pas à vous demander lequel employer dans quelle situation, contrairement à d'autres systèmes. Si le caractère { est immédiatement suivi d'un espace, d'un guillemet ou d'un autre { ou }, Latte n'y voit pas le début d'une balise, ce qui vous permet d'utiliser sans souci des constructions JavaScript, du JSON ou des règles CSS dans vos templates.

Consultez l'aperçu de toutes les balises. Vous pouvez en outre créer vos propres balises personnalisées. Vous pouvez aussi changer les délimiteurs { } ou les désactiver complètement (avec {syntax double}, {syntax off} ou l'attribut n:syntax) ; voyez changement de syntaxe.

Latte comprend PHP

À l'intérieur des balises, vous pouvez utiliser les expressions PHP qui vous sont familières :

Latte enrichit par ailleurs la syntaxe de PHP de quelques extensions plaisantes.

n:attributs

Toute balise paire, comme {if} … {/if}, qui agit sur un seul élément HTML peut se réécrire sous forme de n:attribut. Le {foreach} de l'exemple d'introduction pourrait ainsi s'écrire :

<ul n:if=$items>
	<li n:foreach="$items as $item">{$item|capitalize}</li>
</ul>

La fonctionnalité s'applique alors à l'élément HTML dans lequel elle est placée :

{var $items = ['I', '♥', 'Latte']}

<p n:foreach="$items as $item">{$item}</p>

affiche :

<p>I</p>
<p>♥</p>
<p>Latte</p>

Grâce au préfixe inner-, nous pouvons modifier ce comportement pour qu'il ne s'applique qu'à l'intérieur de l'élément :

<div n:inner-foreach="$items as $item">
	<p>{$item}</p>
	<hr>
</div>

Affiche :

<div>
	<p>I</p>
	<hr>
	<p>♥</p>
	<hr>
	<p>Latte</p>
	<hr>
</div>

Ou bien, avec le préfixe tag-, nous n'appliquons la fonctionnalité qu'aux balises HTML elles-mêmes :

<p><a href={$url} n:tag-if="$url">Title</a></p>

Ce qui affiche, selon la variable $url :

{* quand $url est vide *}
<p>Title</p>

{* quand $url contient 'https://nette.org' *}
<p><a href="https://nette.org">Title</a></p>

Les n:attributs ne sont toutefois pas qu'un raccourci pour les balises paires : il en existe aussi de purs, par exemple le meilleur ami du codeur n:class ou le très pratique n:href.

Outre la syntaxe avec guillemets <div n:if="$foo">, vous pouvez employer la syntaxe alternative à accolades <div n:if={$foo}>. Son principal avantage est de vous laisser utiliser librement guillemets simples et doubles à l'intérieur de {...} :

<div n:if={str_contains($val, "foo")}> ... </div>

Attributs HTML intelligents

Latte rend le travail avec les attributs HTML standard incroyablement simple. Il gère pour vous les attributs booléens comme checked, supprime les attributs valant null et vous laisse composer les valeurs de class et style à l'aide de tableaux. Il sérialise même automatiquement en JSON les données des attributs data-.

{* null supprime l'attribut *}
<div title={$title}>

{* un booléen pilote la présence des attributs booléens *}
<input type="checkbox" checked={$isChecked}>

{* les tableaux fonctionnent dans class *}
<div class={['btn', 'btn-primary', active => $isActive]}>

{* les tableaux sont encodés en JSON dans les attributs data- *}
<div data-config={[theme: dark, version: 2]}>

Pour en savoir plus, voyez le chapitre dédié Attributs HTML intelligents.

Filtres

Consultez l'aperçu des filtres standard.

Les filtres s'écrivent après la barre verticale (un espace peut la précéder) :

<h1>{$heading|upper}</h1>

Les filtres peuvent s'enchaîner et s'appliquent alors de gauche à droite :

<h1>{$heading|lower|capitalize}</h1>

Les arguments suivent le nom du filtre après un deux-points, les suivants étant séparés par des virgules ; un appel entre parenthèses fonctionne également :

<h1>{$heading|truncate:20,''}</h1>
<h1>{$heading|truncate(20, '')}</h1>

Les filtres peuvent aussi s'appliquer à une expression :

{var $name = ($title|upper) . ($subtitle|lower)}

À un bloc :

<h1>{block |lower}{$heading}{/block}</h1>

Ou directement à une valeur (en combinaison avec la balise {=expr}) :

<h1>{='  Hello world  '|trim}</h1>

Si la valeur peut être null et que vous voulez éviter d'appliquer le filtre dans ce cas, utilisez le filtre nullsafe ?| :

<h1>{$heading?|upper}</h1>

Balises HTML dynamiques

Latte prend en charge les balises HTML dynamiques, utiles quand vous avez besoin de souplesse dans les noms de balises :

<h{$level}>Heading</h{$level}>

Le code ci-dessus peut par exemple générer <h1>Heading</h1> ou <h2>Heading</h2> selon la valeur de la variable $level. Les balises HTML dynamiques doivent toujours être paires dans Latte. Leur alternative est n:tag.

Parce que Latte est un système de templates sûr, il vérifie que le nom de balise obtenu est valide et ne contient aucune valeur indésirable ou malveillante. Il garantit aussi que le nom de la balise fermante correspond toujours à celui de la balise ouvrante.

Commentaires

Les commentaires s'écrivent ainsi et n'apparaissent pas dans la sortie :

{* ceci est un commentaire en Latte *}

Les commentaires PHP fonctionnent à l'intérieur des balises :

{include 'file.info', /* value: 123 */}

Gestion des espaces

Latte traite les espaces intelligemment. Vous pouvez indenter votre code librement pour le rendre lisible, la sortie reste propre. Quand une balise de contrôle est seule sur une ligne, toute la ligne (indentation et saut de ligne) disparaît de la sortie (cela ne vaut pas pour les balises qui affichent quelque chose, comme {$var}, {=...} ou {_...}, qui conservent leur indentation et leur saut de ligne final) :

<ul>
	{foreach $items as $item}
	<li>{$item}</li>
	{/foreach}
</ul>

Affiche :

<ul>
	<li>foo</li>
	<li>bar</li>
</ul>

Et si une balise n'est pas seule sur sa ligne, mais côtoie d'autres contenus ? L'espace qui précède la balise appartient alors à l'intérieur de la balise :

<div>
	{if $foo}hello{/if}
</div>

L'indentation se retrouve de fait à l'intérieur du {if} : quand $foo est faux, rien n'est affiché, pas même l'indentation ou une ligne vide. Quand $foo est vrai, la sortie contient naturellement l'indentation. Vous écrivez simplement des templates bien structurés et la sortie reste toujours propre.

Pour une sortie encore plus nette, vous pouvez activer la fonctionnalité Dedent, qui supprime en plus l'indentation due à l'imbrication dans des balises paires comme {if} ou {foreach}.

Sucre syntaxique

Chaînes sans guillemets

Les guillemets peuvent être omis pour les chaînes simples :

comme en PHP : {var $arr = ['hello', 'btn--default', '€']}

en abrégé :    {var $arr = [hello, btn--default, €]}

Les chaînes simples sont celles composées uniquement de lettres, de chiffres, de tirets bas, de traits d'union et de points. Elles ne doivent pas commencer par un chiffre ni commencer ou finir par un trait d'union. Elles ne doivent pas être composées uniquement de majuscules et de tirets bas, car elles seraient alors prises pour des constantes (par ex. PHP_VERSION). Et elles ne doivent pas entrer en conflit avec les mots-clés : and, array, clone, default, false, in, instanceof, new, null, or, return, true, xor.

Constantes

Utilisez le séparateur d'espace de noms global pour distinguer les constantes globales des chaînes simples :

{if \PROJECT_ID === 1} ... {/if}

Cette notation est parfaitement valide en PHP lui-même, où la barre oblique inverse indique que la constante se trouve dans l'espace de noms global.

Opérateur ternaire abrégé

Si la troisième valeur de l'opérateur ternaire est vide, elle peut être omise :

comme en PHP : {$stock ? 'En stock' : ''}

en abrégé :    {$stock ? 'En stock'}

Notation moderne des clés dans un tableau

Les clés d'un tableau peuvent s'écrire comme les paramètres nommés lors d'un appel de fonction :

comme en PHP : {var $arr = ['one' => 'item 1', 'two' => 'item 2']}

en moderne :   {var $arr = [one: 'item 1', two: 'item 2']}

Filtres

Les filtres peuvent s'appliquer à n'importe quelle expression ; il suffit d'entourer l'expression entière de parenthèses :

{var $content = ($text|truncate: 30|upper)}

Opérateur in

L'opérateur in peut remplacer la fonction in_array(). La comparaison est toujours stricte :

{* comme in_array($item, $items, true) *}
{if $item in $items}
	...
{/if}

Une fenêtre sur l'histoire

Au fil de son histoire, Latte a introduit plusieurs éléments de sucre syntaxique apparus dans PHP lui-même quelques années plus tard. Dans Latte, on pouvait par exemple écrire les tableaux [1, 2, 3] au lieu de array(1, 2, 3), ou utiliser l'opérateur nullsafe $obj?->foo bien avant que PHP ne le permette. Latte a aussi introduit l'opérateur de développement de tableau (expand) $arr, équivalent de l'actuel opérateur ...$arr de PHP.

Limitations de PHP dans Latte

Seules des expressions PHP peuvent s'écrire dans Latte. Autrement dit, les instructions terminées par un point-virgule sont exclues. Vous ne pouvez pas déclarer de classes ni utiliser les structures de contrôle telles que if, foreach, switch, return, try, throw et consorts, pour lesquelles Latte propose ses balises. Vous ne pouvez pas non plus utiliser les attributs, les accents graves ou certaines constantes magiques. Vous ne pouvez pas davantage employer unset, echo, include, require, exit, eval, car ce ne sont pas des fonctions mais des constructions particulières du langage PHP, et donc pas des expressions. Seuls les commentaires multilignes /* ... */ sont pris en charge.

Ces limitations peuvent toutefois être contournées en activant l'extension RawPhpExtension, qui vous permet d'utiliser n'importe quel code PHP dans la balise {php ...}, sous la responsabilité de l'auteur du template.

version: 3.x