Șabloane
Nette utilizează sistemul de șabloane Latte. Latte este utilizat deoarece este cel mai sigur sistem de șabloane pentru PHP și, în același timp, cel mai intuitiv sistem. Nu trebuie să învățați prea multe lucruri noi, trebuie doar să cunoașteți PHP și câteva etichete Latte.
Este obișnuit ca pagina să fie completată din șablonul layout + șablonul de acțiune. Iată cum ar putea arăta un șablon
layout, observați blocurile {block}
și tag-ul {include}
:
<!DOCTYPE html>
<html>
<head>
<title>{block title}My App{/block}</title>
</head>
<body>
<header>...</header>
{include content}
<footer>...</footer>
</body>
</html>
Iar acesta ar putea fi șablonul de acțiune:
{block title}Homepage{/block}
{block content}
<h1>Homepage</h1>
...
{/block}
Acesta definește blocul content
, care este inserat în locul lui {include content}
în machetă și,
de asemenea, redefinește blocul title
, care suprascrie {block title}
în machetă. Încercați să vă
imaginați rezultatul.
Căutarea șablonului
În prezentări, nu trebuie să specificați ce șablon trebuie redat; cadrul va determina automat calea, ceea ce vă ușurează codificarea.
Dacă utilizați o structură de directoare în care fiecare prezentator are propriul director, plasați pur și simplu
șablonul în acest director sub numele acțiunii (de exemplu, view). De exemplu, pentru acțiunea default
,
utilizați șablonul default.latte
:
app/ └── UI/ └── Home/ ├── HomePresenter.php └── default.latte
Dacă utilizați o structură în care prezentatorii sunt împreună într-un singur director, iar șabloanele într-un dosar
templates
, salvați-l fie într-un fișier <Presenter>.<view>.latte
sau
<Presenter>/<view>.latte
:
app/ └── Presenters/ ├── HomePresenter.php └── templates/ ├── Home.default.latte ← 1st variant └── Home/ └── default.latte ← 2nd variant
Directorul templates
poate fi, de asemenea, plasat un nivel mai sus, la același nivel cu directorul cu clasele de
prezentatori.
În cazul în care șablonul nu este găsit, prezentatorul răspunde cu eroarea 404 – page not found.
Puteți schimba vizualizarea folosind $this->setView('anotherView')
. De asemenea, este posibilă specificarea
directă a fișierului șablon cu $this->template->setFile('/path/to/template.latte')
.
Fișierele în care sunt căutate șabloanele pot fi modificate prin suprascrierea metodei formatTemplateFiles(), care returnează o matrice de nume de fișiere posibile.
Căutarea șabloanelor de prezentare
De asemenea, Nette caută automat fișierul de machetare.
Dacă folosiți o structură de directoare în care fiecare prezentator are propriul director, plasați macheta fie în folderul cu prezentatorul, dacă este specifică doar acestuia, fie la un nivel superior, dacă este comună mai multor prezentatori:
app/ └── UI/ ├── @layout.latte ← common layout └── Home/ ├── @layout.latte ← only for Home presenter ├── HomePresenter.php └── default.latte
Dacă utilizați o structură în care prezentatorii sunt grupați într-un singur director, iar șabloanele se află într-un
dosar templates
, macheta va fi așteptată în următoarele locuri:
app/ └── Presenters/ ├── HomePresenter.php └── templates/ ├── @layout.latte ← common layout ├── Home.@layout.latte ← only for Home, 1st variant └── Home/ └── @layout.latte ← only for Home, 2nd variant
Dacă prezentatorul se află într-un modul, se va căuta și mai sus în arborele de directoare, în funcție de structura de anvelopare a modulului.
Numele prezentării poate fi schimbat folosind $this->setLayout('layoutAdmin')
și apoi va fi așteptat în
fișierul @layoutAdmin.latte
. De asemenea, puteți specifica direct fișierul șablon de prezentare folosind
$this->setLayout('/path/to/template.latte')
.
Utilizarea $this->setLayout(false)
sau a etichetei {layout none}
în interiorul șablonului
dezactivează căutarea de layout.
Fișierele în care sunt căutate șabloanele de prezentare pot fi modificate prin suprascrierea metodei formatLayoutTemplateFiles(), care returnează o matrice de nume de fișiere posibile.
Variabilele din șablon
Variabilele sunt transmise șablonului prin scrierea lor pe $this->template
și apoi sunt disponibile în
șablon ca variabile locale:
$this->template->article = $this->articles->getById($id);
În acest fel, putem trece cu ușurință orice variabile în șabloane. Cu toate acestea, atunci când dezvoltăm aplicații robuste, este adesea mai util să ne limităm. De exemplu, prin definirea explicită a unei liste de variabile pe care șablonul le așteaptă și a tipurilor acestora. Acest lucru va permite PHP să verifice tipul, IDE-ului să se autocompleteze corect, iar analizei statice să detecteze erorile.
Și cum definim o astfel de enumerare? Pur și simplu sub forma unei clase și a proprietăților sale. O denumim în mod
similar cu presenter, dar cu Template
la sfârșit:
/**
* @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;
// și alte variabile
}
Obiectul $this->template
din prezentator va fi acum o instanță a clasei ArticleTemplate
.
Astfel, PHP va verifica tipurile declarate atunci când acestea sunt scrise. Începând cu PHP 8.2, PHP va avertiza, de asemenea,
în cazul în care se scrie pe o variabilă inexistentă; în versiunile anterioare, același lucru poate fi realizat cu ajutorul
trăsăturii Nette\SmartObject.
Adnotarea @property-read
este pentru IDE și analiza statică, va face ca autocompletarea să funcționeze, a se
vedea PhpStorm și finalizarea codului pentru
$this->template.
Vă puteți permite și luxul de a șopti în șabloane, trebuie doar să instalați pluginul în PhpStorm și să specificați numele clasei la începutul șablonului, consultați articolul Latte: cum se tastează sistemul:
{templateType App\UI\Article\ArticleTemplate}
...
Acesta este, de asemenea, modul în care funcționează șabloanele în componente, trebuie doar să urmați convenția de
denumire și să creați o clasă șablon FifteenTemplate
pentru componentă, de exemplu
FifteenControl
.
Dacă aveți nevoie să creați un $template
ca instanță a unei alte clase, utilizați metoda
createTemplate()
:
public function renderDefault(): void
{
$template = $this->createTemplate(SpecialTemplate::class);
$template->foo = 123;
// ...
$this->sendTemplate($template);
}
Variabile implicite
Prezentatorii și componentele transmit automat mai multe variabile utile către șabloane:
$basePath
este o cale URL absolută către directorul rădăcină (de exemplu,/CD-collection
)$baseUrl
este o adresă URL absolută către directorul rădăcină (de exempluhttp://localhost/CD-collection
)$user
este un obiect care reprezintă utilizatorul$presenter
este prezentatorul curent$control
este componenta sau prezentatorul curent$flashes
lista mesajelor trimise prin metodaflashMessage()
Dacă utilizați o clasă de șablon personalizată, aceste variabile sunt transmise dacă creați o proprietate pentru ele.
Crearea legăturilor
În șablon, creăm legături către alți prezentatori și acțiuni după cum urmează:
<a n:href="Product:show">detail</a>
Atributul n:href
este foarte util pentru etichetele HTML <a>
. Dacă dorim să imprimăm link-ul
în altă parte, de exemplu în text, folosim {link}
:
URL is: {link Home:default}
Pentru mai multe informații, consultați Crearea de linkuri.
Filtre personalizate, etichete etc.
Sistemul de modelare Latte poate fi extins cu filtre, funcții, etichete etc. personalizate. Acest lucru se poate face direct
în render<View>
sau beforeRender()
:
public function beforeRender(): void
{
// adăugarea unui filtru
$this->template->addFilter('foo', /* ... */);
// sau configurați direct obiectul Latte\Engine
$latte = $this->template->getLatte();
$latte->addFilterLoader(/* ... */);
}
Latte versiunea 3 oferă o metodă mai avansată prin crearea unei extensii pentru fiecare proiect web. Iată un exemplu aproximativ al unei astfel de clase:
namespace App\UI\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()),
// ...
];
}
// ...
}
O înregistrăm folosind configuration:
latte:
extensions:
- App\UI\Accessory\LatteExtension
Traducerea
Dacă programați o aplicație multilingvă, probabil că va trebui să scoateți o parte din textul din șablon în diferite
limbi. Pentru a face acest lucru, Nette Framework definește o interfață de traducere Nette\Localization\Translator, care are
o singură metodă translate()
. Aceasta acceptă mesajul $message
, care este de obicei un șir de
caractere, și orice alți parametri. Sarcina este de a returna șirul tradus. Nu există o implementare implicită în Nette,
puteți alege în funcție de nevoile dumneavoastră din mai multe soluții gata făcute care pot fi găsite pe Componette. Documentația acestora vă spune cum să configurați
traducătorul.
Șabloanele pot fi configurate cu un traducător, pe care ni-l vom trece, folosind metoda
setTranslator()
:
protected function beforeRender(): void
{
// ...
$this->template->setTranslator($translator);
}
Alternativ, traducătorul poate fi setat cu ajutorul configurației:
latte:
extensions:
- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
Traducătorul poate fi apoi utilizat, de exemplu, ca filtru |translate
, cu parametri suplimentari trecuți la
metoda translate()
(a se vedea foo, bar
):
<a href="basket">{='Basket'|translate}</a>
<span>{$item|translate}</span>
<span>{$item|translate, foo, bar}</span>
Sau ca o etichetă de subliniere:
<a href="basket">{_'Basket'}</a>
<span>{_$item}</span>
<span>{_$item, foo, bar}</span>
Pentru traducerea secțiunii de șablon, există o etichetă pereche {translate}
(de la Latte 2.11, anterior se
folosea eticheta {_}
):
<a href="order">{translate}Order{/translate}</a>
<a href="order">{translate foo, bar}Order{/translate}</a>
Traducătorul este apelat în mod implicit în timpul execuției la redarea șablonului. Cu toate acestea, versiunea 3 a Latte poate traduce tot textul static în timpul compilării șablonului. Acest lucru economisește performanță, deoarece fiecare șir de caractere este tradus o singură dată, iar traducerea rezultată este scrisă în formularul compilat. Astfel, se creează mai multe versiuni compilate ale șablonului în directorul cache, una pentru fiecare limbă. Pentru a face acest lucru, trebuie doar să specificați limba ca al doilea parametru:
protected function beforeRender(): void
{
// ...
$this->template->setTranslator($translator, $lang);
}
Prin text static înțelegem, de exemplu, {_'hello'}
sau {translate}hello{/translate}
. Textul
nestatic, cum ar fi {_$foo}
, va continua să fie compilat din mers.