Template
Nette utilizza il sistema di templating Latte. Questo perché è il sistema di templating più sicuro per PHP, e allo stesso tempo il sistema più intuitivo. Non devi imparare molto di nuovo, ti basta la conoscenza di PHP e alcuni tag.
È comune che una pagina sia composta da un template di layout + il template dell'azione specifica. Ecco come potrebbe apparire
un template di layout, nota i blocchi {block}
e il tag {include}
:
<!DOCTYPE html>
<html>
<head>
<title>{block title}La mia App{/block}</title>
</head>
<body>
<header>...</header>
{include content}
<footer>...</footer>
</body>
</html>
E questo sarà il template dell'azione:
{block title}Homepage{/block}
{block content}
<h1>Homepage</h1>
...
{/block}
Definisce il blocco content
, che verrà inserito al posto di {include content}
nel layout, e
ridefinisce anche il blocco title
, che sovrascriverà {block title}
nel layout. Prova a immaginare il
risultato.
Ricerca dei template
Non devi specificare nei presenter quale template deve essere renderizzato, il framework deduce il percorso da solo e ti risparmia la scrittura.
Se utilizzi una struttura di directory in cui ogni presenter ha la propria directory, posiziona semplicemente il template in
questa directory con il nome dell'azione (o view), cioè per l'azione default
usa il template
default.latte
:
app/ └── Presentation/ └── Home/ ├── HomePresenter.php └── default.latte
Se utilizzi una struttura in cui i presenter sono insieme in una directory e i template nella cartella
templates
, salvalo o nel file <Presenter>.<view>.latte
o
<Presenter>/<view>.latte
:
app/ └── Presenters/ ├── HomePresenter.php └── templates/ ├── Home.default.latte ← 1a variante └── Home/ └── default.latte ← 2a variante
La directory templates
può trovarsi anche un livello sopra, cioè allo stesso livello della directory con le
classi dei presenter.
Se il template non viene trovato, il presenter risponde con un errore 404 – page not found.
La view viene cambiata usando $this->setView('altraView')
. È anche possibile specificare direttamente il file
del template usando $this->template->setFile('/path/to/template.latte')
.
I file in cui vengono cercati i template possono essere modificati sovrascrivendo il metodo formatTemplateFiles(), che restituisce un array di possibili nomi di file.
Ricerca del template di layout
Nette cerca automaticamente anche il file di layout.
Se utilizzi una struttura di directory in cui ogni presenter ha la propria directory, posiziona il layout o nella cartella con il presenter, se è specifico solo per esso, o un livello sopra, se è comune a più presenter:
app/ └── Presentation/ ├── @layout.latte ← layout comune └── Home/ ├── @layout.latte ← solo per il presenter Home ├── HomePresenter.php └── default.latte
Se utilizzi una struttura in cui i presenter sono insieme in una directory e i template nella cartella
templates
, il layout sarà atteso in queste posizioni:
app/ └── Presenters/ ├── HomePresenter.php └── templates/ ├── @layout.latte ← layout comune ├── Home.@layout.latte ← solo per Home, 1a variante └── Home/ └── @layout.latte ← solo per Home, 2a variante
Se il presenter si trova in un modulo, la ricerca avverrà anche ai livelli di directory superiori, in base alla nidificazione del modulo.
Il nome del layout può essere cambiato usando $this->setLayout('layoutAdmin')
e quindi sarà atteso nel file
@layoutAdmin.latte
. È anche possibile specificare direttamente il file del template di layout usando
$this->setLayout('/path/to/template.latte')
.
Usando $this->setLayout(false)
o il tag {layout none}
all'interno del template, la ricerca del
layout viene disattivata.
I file in cui vengono cercati i template di layout possono essere modificati sovrascrivendo il metodo formatLayoutTemplateFiles(), che restituisce un array di possibili nomi di file.
Variabili nel template
Passiamo le variabili al template scrivendole in $this->template
e poi le abbiamo disponibili nel template come
variabili locali:
$this->template->article = $this->articles->getById($id);
In questo modo semplice possiamo passare qualsiasi variabile ai template. Tuttavia, nello sviluppo di applicazioni robuste, è più utile limitarsi. Ad esempio, definendo esplicitamente l'elenco delle variabili che il template si aspetta e i loro tipi. Grazie a ciò, PHP potrà controllare i tipi, l'IDE suggerirà correttamente e l'analisi statica rivelerà errori.
E come definiamo tale elenco? Semplicemente sotto forma di una classe e delle sue properties. La nominiamo in modo simile al
presenter, ma con Template
alla fine:
/**
* @property-read ArticleTemplate $template
*/
class ArticlePresenter extends Nette\Application\UI\Presenter
{
}
class ArticleTemplate extends Nette\Bridges\ApplicationLatte\Template
{
public Model\Article $article;
public Nette\Security\User $user;
// e altre variabili
}
L'oggetto $this->template
nel presenter sarà ora un'istanza della classe ArticleTemplate
. Quindi
PHP controllerà i tipi dichiarati durante la scrittura. E a partire dalla versione PHP 8.2 avviserà anche sulla scrittura in
una variabile inesistente, nelle versioni precedenti si può ottenere lo stesso risultato usando il trait Nette\SmartObject.
L'annotazione @property-read
è destinata all'IDE e all'analisi statica, grazie ad essa funzionerà il
suggerimento, vedi PhpStorm and code completion
for $this->template.

Puoi goderti il lusso del suggerimento anche nei template, basta installare il plugin per Latte in PhpStorm e specificare all'inizio del template il nome della classe, maggiori informazioni nell'articolo Latte: jak na typový systém:
{templateType App\Presentation\Article\ArticleTemplate}
...
Così funzionano anche i template nei componenti, basta solo rispettare la convenzione di denominazione e per un componente ad
es. FifteenControl
creare una classe di template FifteenTemplate
.
Se hai bisogno di creare $template
come istanza di un'altra classe, utilizza il metodo
createTemplate()
:
public function renderDefault(): void
{
$template = $this->createTemplate(SpecialTemplate::class);
$template->foo = 123;
// ...
$this->sendTemplate($template);
}
Variabili predefinite
I presenter e i componenti passano automaticamente diverse variabili utili ai template:
$basePath
è il percorso URL assoluto alla directory principale (es./eshop
)$baseUrl
è l'URL assoluto alla directory principale (es.http://localhost/eshop
)$user
è l'oggetto che rappresenta l'utente$presenter
è il presenter corrente$control
è il componente o presenter corrente$flashes
è l'array di messaggi inviati dalla funzioneflashMessage()
Se utilizzi una classe di template personalizzata, queste variabili vengono passate se crei una property per esse.
Creazione di link
Nel template, i link ad altri presenter & azioni vengono creati in questo modo:
<a n:href="Product:show">dettaglio prodotto</a>
L'attributo n:href
è molto utile per i tag HTML <a>
. Se vogliamo stampare il link altrove, ad
esempio nel testo, usiamo {link}
:
L'indirizzo è: {link Home:default}
Maggiori informazioni si trovano nel capitolo Creazione di link URL.
Filtri personalizzati, tag, ecc.
Il sistema di templating Latte può essere esteso con filtri, funzioni, tag personalizzati, ecc. Ciò può essere fatto
direttamente nel metodo render<View>
o beforeRender()
:
public function beforeRender(): void
{
// aggiunta di un filtro
$this->template->addFilter('foo', /* ... */);
// o configuriamo direttamente l'oggetto Latte\Engine
$latte = $this->template->getLatte();
$latte->addFilterLoader(/* ... */);
}
Latte nella versione 3 offre un modo più avanzato, ovvero creare un'extension per ogni progetto web. Esempio parziale di tale classe:
namespace App\Presentation\Accessory;
final class LatteExtension extends Latte\Extension
{
public function __construct(
private App\Model\Facade $facade,
private Nette\Security\User $user,
// ...
) {
}
public function getFilters(): array
{
return [
'timeAgoInWords' => $this->filterTimeAgoInWords(...),
'money' => $this->filterMoney(...),
// ...
];
}
public function getFunctions(): array
{
return [
'canEditArticle' =>
fn($article) => $this->facade->canEditArticle($article, $this->user->getId()),
// ...
];
}
// ...
}
La registriamo tramite la configurazione:
latte:
extensions:
- App\Presentation\Accessory\LatteExtension
Traduzione
Se programmi un'applicazione multilingue, probabilmente avrai bisogno di stampare alcuni testi nel template in diverse lingue.
Nette Framework definisce a tale scopo un'interfaccia per la traduzione Nette\Localization\Translator, che ha un unico
metodo translate()
. Questo accetta il messaggio $message
, che di solito è una stringa, e qualsiasi
altro parametro. Il compito è restituire la stringa tradotta. In Nette non c'è un'implementazione predefinita, puoi scegliere in
base alle tue esigenze tra diverse soluzioni pronte, che trovi su Componette. Nella loro documentazione imparerai come configurare il
translator.
Ai template è possibile impostare un traduttore, che ci facciamo passare, con il metodo
setTranslator()
:
protected function beforeRender(): void
{
// ...
$this->template->setTranslator($translator);
}
Il translator può alternativamente essere impostato tramite la configurazione:
latte:
extensions:
- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
Successivamente, il traduttore può essere utilizzato ad esempio come filtro |translate
, inclusi parametri
aggiuntivi che vengono passati al metodo translate()
(vedi foo, bar
):
<a href="basket">{='Carrello'|translate}</a>
<span>{$item|translate}</span>
<span>{$item|translate, foo, bar}</span>
O come tag con trattino basso:
<a href="basket">{_'Carrello'}</a>
<span>{_$item}</span>
<span>{_$item, foo, bar}</span>
Per la traduzione di una sezione del template esiste un tag di coppia {translate}
(da Latte 2.11, prima si usava
il tag {_}
):
<a href="order">{translate}Ordine{/translate}</a>
<a href="order">{translate foo, bar}Ordine{/translate}</a>
Il translator viene chiamato standardmente durante l'esecuzione al rendering del template. Latte versione 3, tuttavia, può tradurre tutti i testi statici già durante la compilazione del template. Ciò consente di risparmiare prestazioni, poiché ogni stringa viene tradotta solo una volta e la traduzione risultante viene scritta nella forma compilata. Nella directory della cache vengono così create più versioni compilate del template, una per ogni lingua. Per fare ciò, basta solo specificare la lingua come secondo parametro:
protected function beforeRender(): void
{
// ...
$this->template->setTranslator($translator, $lang);
}
Per testo statico si intende ad esempio {_'ciao'}
o {translate}ciao{/translate}
. I testi non
statici, come ad esempio {_$foo}
, continueranno ad essere tradotti durante l'esecuzione.