Modelli
Nette utilizza il sistema di template Latte. Latte è utilizzato perché è il sistema di template più sicuro per PHP e allo stesso tempo il più intuitivo. Non è necessario imparare molto di nuovo, basta conoscere PHP e alcuni tag di Latte.
Di solito la pagina viene completata dal modello di layout + il modello di azione. Ecco come potrebbe apparire un modello di
layout, notando i blocchi {block}
e il tag {include}
:
<!DOCTYPE html>
<html>
<head>
<title>{block title}My App{/block}</title>
</head>
<body>
<header>...</header>
{include content}
<footer>...</footer>
</body>
</html>
E questo potrebbe essere il modello di azione:
{block title}Homepage{/block}
{block content}
<h1>Homepage</h1>
...
{/block}
Definisce il blocco content
, che viene inserito al posto di {include content}
nel layout, e
ridefinisce anche il blocco title
, che sovrascrive {block title}
nel layout. Provate a immaginare il
risultato.
Ricerca dei modelli
Il percorso dei modelli viene dedotto secondo una semplice logica. Si cerca di vedere se uno di questi file di template esiste
relativamente alla directory in cui si trova la classe del presentatore, dove <Presenter>
è il nome del
presentatore corrente e <view>
è il nome dell'azione corrente:
templates/<Presenter>/<view>.latte
templates/<Presenter>.<view>.latte
Se il modello non viene trovato, si cercherà nella cartella templates
a un livello superiore, cioè allo stesso
livello della cartella con la classe del presentatore.
Se il modello non viene trovato nemmeno lì, la risposta è un errore 404.
Si può anche cambiare la vista usando $this->setView('otherView')
. Oppure, invece di cercare, specificare
direttamente il nome del file del template usando $this->template->setFile('/path/to/template.latte')
.
È possibile modificare i percorsi in cui vengono cercati i modelli sovrascrivendo il metodo formatTemplateFiles, che restituisce un array di possibili percorsi di file.
Il layout è previsto nei seguenti file:
templates/<Presenter>/@<layout>.latte
templates/<Presenter>.@<layout>.latte
templates/@<layout>.latte
layout comune a più presentatori
<Presenter>
è il nome del presentatore corrente e <layout>
è il nome del layout, che
per impostazione predefinita è 'layout'
. Il nome può essere modificato con
$this->setLayout('otherLayout')
, in modo da provare i file @otherLayout.latte
.
È anche possibile specificare direttamente il nome del file del modello di layout con
$this->setLayout('/path/to/template.latte')
. L'uso di $this->setLayout(false)
disabilita la
ricerca dei layout.
È possibile modificare i percorsi in cui vengono cercati i modelli sovrascrivendo il metodo formatLayoutTemplateFiles, che restituisce un array di possibili percorsi di file.
Variabili nel modello
Le variabili vengono passate al template scrivendole in $this->template
e poi sono disponibili nel template
come variabili locali:
$this->template->article = $this->articles->getById($id);
In questo modo possiamo passare facilmente qualsiasi variabile ai template. Tuttavia, quando si sviluppano applicazioni robuste, spesso è più utile limitarsi. Per esempio, definendo esplicitamente un elenco di variabili che il template si aspetta e i loro tipi. Ciò consentirà a PHP di effettuare il controllo dei tipi, all'IDE di effettuare il completamento automatico in modo corretto e all'analisi statica di rilevare gli errori.
Come si definisce un'enumerazione di questo tipo? Semplicemente sotto forma di una classe e delle sue proprietà. La chiamiamo
in modo simile a 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 presentatore sarà ora un'istanza della classe ArticleTemplate
.
Quindi PHP controllerà i tipi dichiarati quando vengono scritti. A partire da PHP 8.2, inoltre, avvertirà di scrivere su una
variabile inesistente; nelle versioni precedenti si può ottenere lo stesso risultato utilizzando il tratto Nette\SmartObject.
L'annotazione @property-read
è per l'IDE e l'analisi statica, farà funzionare il completamento automatico,
vedere PhpStorm e il completamento del codice
per $this->template.

Ci si può concedere il lusso di sussurrare anche nei template, basta installare il plugin Latte in PhpStorm e specificare il nome della classe all'inizio del template, si veda l'articolo Latte: come digitare il sistema:
{templateType App\Presenters\ArticleTemplate}
...
Questo è anche il modo in cui i template funzionano nei componenti, basta seguire la convenzione di denominazione e creare
una classe template FifteenTemplate
per il componente, ad esempio FifteenControl
.
Se si vuole creare una classe $template
come istanza di un'altra classe, usare il metodo
createTemplate()
:
public function renderDefault(): void
{
$template = $this->createTemplate(SpecialTemplate::class);
$template->foo = 123;
// ...
$this->sendTemplate($template);
}
Variabili predefinite
I presentatori e i componenti passano automaticamente diverse variabili utili ai modelli:
$basePath
è un percorso URL assoluto alla cartella principale (ad esempio/CD-collection
)$baseUrl
è un URL assoluto alla cartella principale (per esempiohttp://localhost/CD-collection
)$user
è un oggetto che rappresenta l'utente$presenter
è il presentatore corrente$control
è il componente o presentatore corrente$flashes
è un elenco di messaggi inviati dal metodoflashMessage()
Se si utilizza una classe modello personalizzata, queste variabili vengono passate se si crea una proprietà per esse.
Creazione di collegamenti
Nel modello si creano collegamenti ad altri presentatori e azioni come segue:
<a n:href="Product:show">detail</a>
L'attributo n:href
è molto utile per i tag HTML <a>
. Se vogliamo stampare il link altrove, ad
esempio nel testo, usiamo {link}
:
URL is: {link Home:default}
Per ulteriori informazioni, vedere Creazione di collegamenti.
Filtri personalizzati, tag, ecc.
Il sistema di template Latte può essere esteso con filtri personalizzati, funzioni, tag, ecc. Questo può essere fatto
direttamente nel metodo render<View>
o nel metodo beforeRender()
:
public function beforeRender(): void
{
// aggiunta di un filtro
$this->template->addFilter('foo', /* ... */);
// oppure configurare direttamente l'oggetto LatteEngine
$latte = $this->template->getLatte();
$latte->addFilterLoader(/* ... */);
}
La versione 3 di Latte offre un metodo più avanzato, creando un'estensione per ogni progetto web. Ecco un esempio approssimativo di una classe di questo tipo:
namespace App\Templating;
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 usando configuration:
latte:
extensions:
- App\Templating\LatteExtension
Tradurre
Se si sta programmando un'applicazione multilingue, è probabile che sia necessario produrre parte del testo del modello in
lingue diverse. A tale scopo, il framework Nette definisce un'interfaccia di 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 è quello di restituire la stringa tradotta. Non esiste un'implementazione predefinita in Nette, ma si
può scegliere in base alle proprie esigenze tra diverse soluzioni già pronte che si possono trovare su Componette. La loro documentazione spiega come configurare il
traduttore.
I modelli possono essere configurati con un traduttore, che ci verrà passato, utilizzando il metodo
setTranslator()
:
protected function beforeRender(): void
{
// ...
$this->template->setTranslator($translator);
}
In alternativa, il traduttore può essere impostato utilizzando la configurazione:
latte:
extensions:
- Latte\Essential\TranslatorExtension
Il traduttore può essere utilizzato, ad esempio, come filtro |translate
, con parametri aggiuntivi passati al
metodo translate()
(vedere foo, bar
):
<a href="basket">{='Basket'|translate}</a>
<span>{$item|translate}</span>
<span>{$item|translate, foo, bar}</span>
Oppure come tag underscore:
<a href="basket">{_'Basket'}</a>
<span>{_$item}</span>
<span>{_$item, foo, bar}</span>
Per la traduzione di sezioni di template, esiste un tag accoppiato {translate}
(da Latte 2.11, in precedenza si
usava il tag {_}
):
<a href="order">{translate}Order{/translate}</a>
<a href="order">{translate foo, bar}Order{/translate}</a>
Il traduttore viene chiamato per impostazione predefinita in fase di esecuzione durante il rendering del template. La versione 3 di Latte, tuttavia, può tradurre tutto il testo statico durante la compilazione del modello. Ciò consente di risparmiare sulle prestazioni, perché ogni stringa viene tradotta una sola volta e la traduzione risultante viene scritta nel modello compilato. In questo modo si creano più versioni compilate del modello nella cartella cache, una per ogni lingua. Per farlo, è sufficiente specificare la lingua come secondo parametro:
protected function beforeRender(): void
{
// ...
$this->template->setTranslator($translator, $lang);
}
Per testo statico si intende, ad esempio, {_'hello'}
o {translate}hello{/translate}
. Il testo non
statico, come {_$foo}
, continuerà a essere compilato al volo.