Sintassi
La sintassi di Latte nasce dalle esigenze pratiche dei web designer. Cercavamo la sintassi più amichevole possibile, con cui scrivere elegantemente costrutti che altrimenti sono una vera sfida. Allo stesso tempo tutte le espressioni si scrivono esattamente come in PHP, quindi non dovete imparare un nuovo linguaggio: sfruttate semplicemente quello che già sapete.
Qui sotto trovate un template minimo che illustra alcuni elementi di base: i tag, gli n:attributi, i commenti e i filtri.
{* questo è un commento *}
<ul n:if=$items> {* n:if è un n:attributo *}
{foreach $items as $item} {* tag che rappresenta un ciclo foreach *}
<li>{$item|capitalize}</li> {* tag che stampa una variabile con un filtro *}
{/foreach} {* fine del ciclo *}
</ul>
Diamo un'occhiata più da vicino a questi elementi importanti e a come possono aiutarvi a creare un template straordinario.
Tag
Un template contiene tag che controllano la logica del template (per esempio i cicli foreach) oppure stampano
espressioni. Per entrambi si usa un unico delimitatore { ... }, così non dovete pensare a quale delimitatore usare
in quale situazione, a differenza di altri sistemi. Se il carattere { è seguito immediatamente da uno spazio, da un
apice o da un altro { o }, Latte non lo considera l'inizio di un tag: potete quindi usare senza
problemi nei vostri template costrutti JavaScript, JSON o regole CSS.
Vedi la panoramica di tutti i tag. Potete inoltre creare i vostri tag personalizzati. Potete anche cambiare i delimitatori { }
o disattivarli del tutto (con {syntax double}, {syntax off} o l'attributo n:syntax); vedi
cambiare la sintassi.
Latte comprende PHP
Dentro i tag potete usare le espressioni PHP che già conoscete:
- variabili
- stringhe (comprese HEREDOC e NOWDOC), array, numeri ecc.
- operatori
- chiamate a funzioni e metodi (che si possono limitare con la sandbox)
- match
- arrow function
- first class callable syntax
- commenti su più righe
/* ... */ - e così via…
Latte arricchisce inoltre la sintassi di PHP con alcune gradevoli estensioni.
n:attributi
Ogni tag di tipo pari, come {if} … {/if}, che opera su un singolo elemento HTML, si può riscrivere sotto forma
di n:attributo. Per esempio il {foreach} dell'esempio introduttivo si potrebbe scrivere anche così:
<ul n:if=$items>
<li n:foreach="$items as $item">{$item|capitalize}</li>
</ul>
La funzionalità si applica allora all'elemento HTML in cui è collocata:
{var $items = ['I', '♥', 'Latte']}
<p n:foreach="$items as $item">{$item}</p>
stampa:
<p>I</p>
<p>♥</p>
<p>Latte</p>
Con il prefisso inner- possiamo modificare il comportamento in modo che si applichi solo alla parte interna
dell'elemento:
<div n:inner-foreach="$items as $item">
<p>{$item}</p>
<hr>
</div>
Stampa:
<div>
<p>I</p>
<hr>
<p>♥</p>
<hr>
<p>Latte</p>
<hr>
</div>
Oppure, con il prefisso tag-, applichiamo la funzionalità solo ai tag HTML in sé:
<p><a href={$url} n:tag-if="$url">Titolo</a></p>
Che stampa, a seconda della variabile $url:
{* quando $url è vuota *}
<p>Titolo</p>
{* quando $url contiene 'https://nette.org' *}
<p><a href="https://nette.org">Titolo</a></p>
Gli n:attributi non sono però solo una scorciatoia per i tag di tipo pari: ne esistono anche di puri, per esempio il migliore amico del programmatore n:class o il comodissimo n:href.
Oltre alla sintassi con gli apici <div n:if="$foo">, potete usare la sintassi alternativa con le parentesi
graffe <div n:if={$foo}>. Il vantaggio principale è che dentro {...} potete usare liberamente sia
gli apici singoli sia quelli doppi:
<div n:if={str_contains($val, "foo")}> ... </div>
Attributi HTML intelligenti
Latte rende incredibilmente semplice il lavoro con gli attributi HTML comuni. Si occupa al posto vostro degli attributi
booleani come checked, elimina gli attributi che contengono null e permette di comporre i valori di
class e style con gli array. Serializza perfino automaticamente in JSON i dati degli attributi
data-.
{* null elimina l'attributo *}
<div title={$title}>
{* un booleano decide la presenza degli attributi booleani *}
<input type="checkbox" checked={$isChecked}>
{* in class funzionano gli array *}
<div class={['btn', 'btn-primary', active => $isActive]}>
{* negli attributi data- gli array vengono codificati in JSON *}
<div data-config={[theme: dark, version: 2]}>
Per saperne di più leggete il capitolo dedicato Attributi HTML intelligenti.
Filtri
Vedi la panoramica dei filtri standard.
I filtri si scrivono dopo il simbolo pipe (uno spazio prima è ammesso):
<h1>{$heading|upper}</h1>
I filtri si possono concatenare e vengono applicati nell'ordine, da sinistra a destra:
<h1>{$heading|lower|capitalize}</h1>
Gli argomenti seguono il nome del filtro dopo i due punti e gli eventuali successivi sono separati da virgole; funziona anche la chiamata tra parentesi:
<h1>{$heading|truncate:20,''}</h1>
<h1>{$heading|truncate(20, '')}</h1>
I filtri si possono applicare anche a un'espressione:
{var $name = ($title|upper) . ($subtitle|lower)}
A un blocco:
<h1>{block |lower}{$heading}{/block}</h1>
Oppure direttamente a un valore (in combinazione con il tag {=expr}):
<h1>{=' Hello world '|trim}</h1>
Se il valore può essere null e in tal caso volete evitare di applicare il filtro, usate il filtro nullsafe ?|:
<h1>{$heading?|upper}</h1>
Tag HTML dinamici
Latte supporta i tag HTML dinamici, utili quando vi serve flessibilità nei nomi dei tag:
<h{$level}>Intestazione</h{$level}>
Per esempio il codice qui sopra può generare <h1>Intestazione</h1> oppure
<h2>Intestazione</h2> a seconda del valore della variabile $level. In Latte i tag HTML
dinamici devono sempre essere di tipo pari. La loro alternativa è n:tag.
Poiché Latte è un sistema di template sicuro, controlla che il nome del tag risultante sia valido e non contenga valori indesiderati o malevoli. Garantisce inoltre che il nome del tag di chiusura corrisponda sempre a quello del tag di apertura.
Commenti
I commenti si scrivono così e non finiscono nell'output:
{* questo è un commento in Latte *}
Dentro i tag funzionano i commenti di PHP:
{include 'file.info', /* value: 123 */}
Gestione degli spazi bianchi
Latte gestisce gli spazi bianchi in modo intelligente. Potete indentare liberamente il codice per renderlo leggibile e l'output
resta pulito. Quando un tag di controllo compare da solo su una riga, l'intera riga (indentazione e a capo) viene rimossa
dall'output (questo non vale per i tag che stampano, come {$var}, {=...} o {_...}, che
conservano la propria indentazione e l'a capo finale):
<ul>
{foreach $items as $item}
<li>{$item}</li>
{/foreach}
</ul>
Stampa:
<ul>
<li>foo</li>
<li>bar</li>
</ul>
E se un tag non è solo sulla riga, ma compare accanto ad altro contenuto? Lo spazio bianco che precede il tag appartiene allora al suo interno:
<div>
{if $foo}hello{/if}
</div>
L'indentazione si trova di fatto dentro {if}: quando $foo è falso non viene stampato nulla, nemmeno
l'indentazione o una riga vuota. Quando $foo è vero, l'output contiene naturalmente l'indentazione. Voi vi limitate
a scrivere template ben strutturati e l'output è sempre pulito.
Per un output ancora più pulito potete attivare la funzionalità Dedent, che rimuove anche l'indentazione dovuta all'annidamento dentro
tag di tipo pari come {if} o {foreach}.
Zucchero sintattico
Stringhe senza apici
Per le stringhe semplici gli apici si possono omettere:
come in PHP: {var $arr = ['hello', 'btn--default', '€']}
abbreviato: {var $arr = [hello, btn--default, €]}
Le stringhe semplici sono quelle composte esclusivamente da lettere, cifre, trattini bassi, trattini e punti. Non devono
iniziare con una cifra e non devono iniziare né finire con un trattino. Non devono essere composte solo da lettere maiuscole e
trattini bassi, perché in tal caso sono considerate costanti (per esempio PHP_VERSION). E non devono entrare in
conflitto con le parole chiave: and, array, clone, default,
false, in, instanceof, new, null, or,
return, true, xor.
Costanti
Usate il separatore del namespace globale per distinguere le costanti globali dalle stringhe semplici:
{if \PROJECT_ID === 1} ... {/if}
Questa notazione è del tutto valida anche in PHP, dove la barra rovesciata indica che la costante si trova nel namespace globale.
Operatore ternario abbreviato
Se il terzo valore dell'operatore ternario è vuoto, si può omettere:
come in PHP: {$stock ? 'Disponibile' : ''}
abbreviato: {$stock ? 'Disponibile'}
Notazione moderna delle chiavi negli array
Le chiavi degli array si possono scrivere come i parametri nominali nelle chiamate di funzione:
come in PHP: {var $arr = ['one' => 'item 1', 'two' => 'item 2']}
moderno: {var $arr = [one: 'item 1', two: 'item 2']}
Filtri
I filtri si possono usare su qualsiasi espressione; basta racchiudere l'intera espressione tra parentesi:
{var $content = ($text|truncate: 30|upper)}
Operatore in
L'operatore in può sostituire la funzione in_array(). Il confronto è sempre rigoroso:
{* come in_array($item, $items, true) *}
{if $item in $items}
...
{/if}
Una finestra sulla storia
Nel corso della sua storia Latte ha introdotto diverse forme di zucchero sintattico comparse in PHP stesso qualche anno dopo.
Per esempio in Latte era possibile scrivere gli array come [1, 2, 3] invece di array(1, 2, 3) oppure
usare l'operatore nullsafe $obj?->foo molto prima che fosse possibile in PHP. Latte ha introdotto anche
l'operatore di espansione degli array (expand) $arr, equivalente all'odierno operatore ...$arr
di PHP.
Limitazioni di PHP in Latte
In Latte si possono scrivere solo espressioni PHP. Non si possono cioè usare istruzioni che terminano con il punto e virgola.
Non potete dichiarare classi né usare strutture di
controllo come if, foreach, switch, return, try,
throw e altre, per le quali Latte offre i suoi tag. Non potete usare
nemmeno gli attributi, i backtick o alcune costanti magiche. Non potete usare unset,
echo, include, require, exit né eval, perché non sono funzioni
ma costrutti speciali del linguaggio PHP e quindi non sono espressioni. Sono supportati solo i commenti su più righe
/* ... */.
Queste limitazioni si possono però aggirare attivando l'estensione RawPhpExtension, che permette di usare qualsiasi codice PHP
dentro il tag {php ...}, sotto la responsabilità dell'autore del template.