Practici de dezvoltare
Instalare
Cel mai bun mod de a instala Latte este folosind Composer:
composer require latte/latte
Versiuni PHP suportate (se aplică pentru ultimele versiuni patch ale Latte):
versiune | compatibil cu PHP |
---|---|
Latte 3.0 | PHP 8.0 – 8.2 |
Cum se randează un șablon
Cum se randează un șablon? Este suficient acest cod simplu:
$latte = new Latte\Engine;
// director pentru cache
$latte->setTempDirectory('/path/to/tempdir');
$params = [ /* variabile șablon */ ];
// sau $params = new TemplateParameters(/* ... */);
// randează la ieșire
$latte->render('template.latte', $params);
// randează într-o variabilă
$output = $latte->renderToString('template.latte', $params);
Parametrii pot fi array-uri sau, și mai bine, un obiect, care asigură verificarea tipului și sugestii în editori.
Exemple de utilizare găsiți și în depozitul Latte examples.
Performanță și cache
Șabloanele în Latte sunt extrem de rapide, deoarece Latte le compilează direct în cod PHP și le salvează în cache pe disc. Prin urmare, nu au nicio suprasarcină suplimentară față de șabloanele scrise în PHP pur.
Cache-ul se regenerează automat de fiecare dată când modificați fișierul sursă. În timpul dezvoltării, editați confortabil șabloanele în Latte și vedeți imediat modificările în browser. Puteți dezactiva această funcție în mediul de producție pentru a economisi puțină performanță:
$latte->setAutoRefresh(false);
La implementarea pe serverul de producție, generarea inițială a cache-ului, în special pentru aplicații mai mari, poate dura, desigur, puțin timp. Latte are încorporată prevenirea “cache stampede”. Este o situație în care un număr mare de cereri concurente ajung simultan, care pornesc Latte, și deoarece cache-ul încă nu există, toate ar începe să-l genereze simultan. Ceea ce ar suprasolicita nejustificat serverul. Latte este inteligent și, în cazul mai multor cereri concurente, generează cache-ul doar primul fir de execuție, celelalte așteaptă și apoi îl utilizează.
Parametrii ca o clasă
Mai bine decât să transmiteți variabilele șablonului ca array este să creați o clasă. Veți obține astfel o scriere sigură din punct de vedere al tipului, sugestii utile în IDE și o cale pentru înregistrarea filtrelor și funcțiilor.
class MailTemplateParameters
{
public function __construct(
public string $lang,
public Address $address,
public string $subject,
public array $items,
public ?float $price = null,
) {}
}
$latte->render('mail.latte', new MailTemplateParameters(
lang: $this->lang,
subject: $title,
price: $this->getPrice(),
items: [],
address: $userAddress,
));
Dezactivarea auto-escapării variabilelor
Dacă o variabilă conține un șir în HTML, o puteți marca astfel încât Latte să nu o escapeze automat (și deci
dublu). Veți evita astfel necesitatea de a specifica în șablon |noescape
.
Cea mai simplă cale este să înfășurați șirul într-un obiect Latte\Runtime\Html
:
$params = [
'articleBody' => new Latte\Runtime\Html($article->htmlBody),
];
Latte nu mai escapează toate obiectele care implementează interfața Latte\HtmlStringable
. Puteți astfel crea
propria clasă, a cărei metodă __toString()
va returna cod HTML care nu va fi escapat automat:
class Emphasis extends Latte\HtmlStringable
{
public function __construct(
private string $str,
) {
}
public function __toString(): string
{
return '<em>' . htmlspecialchars($this->str) . '</em>';
}
}
$params = [
'foo' => new Emphasis('hello'),
];
Metoda __toString
trebuie să returneze HTML corect și să asigure escaparea parametrilor, altfel
poate apărea o vulnerabilitate XSS!
Cum să extindeți Latte cu filtre, tag-uri etc.
Cum să adăugați în Latte propriul filtru, funcție, tag etc? Despre aceasta tratează capitolul extindem Latte. Dacă doriți să reutilizați modificările dvs. în diferite proiecte sau să le partajați cu alții, ar trebui să creați o extensie.
Cod arbitrar în șablon {php ...}
În interiorul tag-ului {do}
se pot scrie doar expresii PHP,
nu puteți, de exemplu, să inserați construcții precum if ... else
sau instrucțiuni terminate cu punct și
virgulă.
Puteți însă înregistra extensia RawPhpExtension
, care adaugă tag-ul {php ...}
. Folosind acesta,
puteți insera orice cod PHP. Nu i se aplică nicio regulă a modului sandbox, utilizarea fiind deci responsabilitatea autorului
șablonului.
$latte->addExtension(new Latte\Essential\RawPhpExtension);
Verificarea codului generat
Latte compilează șabloanele în cod PHP. Desigur, are grijă ca codul generat să fie valid sintactic. Cu toate acestea, la
utilizarea extensiilor terțe sau a RawPhpExtension
, Latte nu poate garanta corectitudinea fișierului generat. De
asemenea, se poate scrie în PHP cod care, deși este sintactic corect, este interzis (de exemplu, atribuirea unei valori
variabilei $this
) și provoacă o eroare de compilare PHP (Compile Error). Dacă scrieți o astfel de operație în
șablon, aceasta ajunge și în codul PHP generat. Deoarece în PHP există peste două sute de operații interzise diferite,
Latte nu are ambiția de a le detecta. Le semnalează abia PHP-ul însuși la randare, ceea ce de obicei nu deranjează.
Există însă situații în care doriți să știți deja în momentul compilării șablonului că nu conține nicio eroare de
compilare PHP. În special atunci când șabloanele pot fi editate de utilizatori sau utilizați Sandbox. În acest caz, lăsați șabloanele să fie verificate deja în timpul
compilării. Activați această funcționalitate cu metoda Engine::enablePhpLint()
. Deoarece pentru verificare are
nevoie să apeleze binarul PHP, transmiteți calea către acesta ca parametru:
$latte = new Latte\Engine;
$latte->enablePhpLinter('/path/to/php');
try {
$latte->compile('home.latte');
} catch (Latte\CompileException $e) {
// prinde erorile din Latte și, de asemenea, Compile Error din PHP
echo 'Error: ' . $e->getMessage();
}
Setări regionale
Latte permite setarea setărilor regionale, care influențează formatarea numerelor, datelor și sortarea. Se setează
folosind metoda setLocale()
. Identificatorul de mediu se ghidează după standardul IETF language tag, care
utilizează extensia PHP intl
. Se compune din codul limbii și, eventual, codul țării, de ex. en_US
pentru engleza din Statele Unite, de_DE
pentru germana din Germania etc.
$latte = new Latte\Engine;
$latte->setLocale('ro_RO');
Setarea mediului influențează filtrele localDate, sort, number și bytes.
Necesită extensia PHP intl
. Setarea în Latte nu influențează setarea globală a locale
în PHP.
Mod strict
În modul strict de parsare, Latte verifică dacă nu lipsesc tag-urile HTML de închidere și, de asemenea, interzice
utilizarea variabilei $this
. Îl activați astfel:
$latte = new Latte\Engine;
$latte->setStrictParsing();
Generarea șabloanelor cu antetul declare(strict_types=1)
o activați astfel:
$latte = new Latte\Engine;
$latte->setStrictTypes();
Traducerea în șabloane
Folosind extensia TranslatorExtension
, adăugați în șablon tag-urile {_...}
, {translate}
și filtrul translate
. Acestea servesc la traducerea valorilor sau a
părților șablonului în alte limbi. Ca parametru specificăm metoda (PHP callable) care efectuează traducerea:
class MyTranslator
{
public function __construct(private string $lang)
{}
public function translate(string $original): string
{
// din $original creăm $translated conform $this->lang
return $translated;
}
}
$translator = new MyTranslator($lang);
$extension = new Latte\Essential\TranslatorExtension(
$translator->translate(...), // [$translator, 'translate'] în PHP 8.0
);
$latte->addExtension($extension);
Translatorul este apelat în timpul rulării la randarea șablonului. Latte poate însă traduce toate textele statice deja în timpul compilării șablonului. Astfel se economisește performanță, deoarece fiecare șir se traduce o singură dată, iar traducerea rezultată se scrie în forma compilată. În directorul cu cache vor apărea astfel mai multe versiuni compilate ale șablonului, una pentru fiecare limbă. Pentru aceasta este suficient doar să specificați limba ca al doilea parametru:
$extension = new Latte\Essential\TranslatorExtension(
$translator->translate(...),
$lang,
);
Prin text static se înțelege, de exemplu, {_'hello'}
sau {translate}hello{/translate}
. Textele
nestatice, cum ar fi {_$foo}
, se vor traduce în continuare în timpul rulării.
Translatorului i se pot transmite din șablon și parametri suplimentari folosind {_$original, foo: bar}
sau
{translate foo: bar}
, pe care îi primește ca array $params
în al doilea argument:
public function translate(string $original, ...$params): string
{
// $params['foo'] === 'bar'
}
Depanare și Tracy
Latte încearcă să vă facă dezvoltarea cât mai plăcută posibil. Direct în scopuri de depanare există trei tag-uri {dump}
, {debugbreak}
și {trace}
.
Cel mai mare confort îl obțineți dacă instalați și excelentul instrument de depanare Tracy și activați add-on-ul pentru Latte:
// pornește Tracy
Tracy\Debugger::enable();
$latte = new Latte\Engine;
// activează extensia pentru Tracy
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);
Acum vi se vor afișa toate erorile într-un ecran roșu clar, inclusiv erorile din șabloane cu evidențierea rândului și coloanei (video). În același timp, în colțul din dreapta jos, în așa-numitul Tracy Bar, va apărea o filă pentru Latte, unde sunt vizibile clar toate șabloanele randate și relațiile lor reciproce (inclusiv posibilitatea de a face clic pentru a ajunge la șablon sau la codul compilat) și, de asemenea, variabilele:

Deoarece Latte compilează șabloanele în cod PHP clar, le puteți parcurge pas cu pas confortabil în IDE-ul dvs.
Linter: validarea sintaxei șabloanelor
Pentru a parcurge toate șabloanele și a verifica dacă nu conțin erori sintactice, vă ajută instrumentul Linter. Se lansează din consolă:
vendor/bin/latte-lint <cale>
Parametrul --strict
activează modul strict.
Dacă utilizați tag-uri personalizate, creați-vă și propria versiune de Linter, de ex. custom-latte-lint
:
#!/usr/bin/env php
<?php
// introduceți calea reală către fișierul autoload.php
require __DIR__ . '/vendor/autoload.php';
$path = $argv[1] ?? '.';
$linter = new Latte\Tools\Linter;
$latte = $linter->getEngine();
// adăugați aici extensiile dvs. individuale
$latte->addExtension(/* ... */);
$ok = $linter->scanDirectory($path);
exit($ok ? 0 : 1);
Alternativ, puteți transmite propriul obiect Latte\Engine
către Linter:
$latte = new Latte\Engine;
// aici configurăm obiectul $latte
$linter = new Latte\Tools\Linter(engine: $latte);
Încărcarea șabloanelor dintr-un șir
Aveți nevoie să încărcați șabloane din șiruri în loc de fișiere, de exemplu în scopuri de testare? Vă ajută StringLoader:
$latte->setLoader(new Latte\Loaders\StringLoader([
'main.file' => '{include other.file}',
'other.file' => '{if true} {$var} {/if}',
]));
$latte->render('main.file', $params);
Gestionar de excepții
Puteți defini propriul handler de deservire pentru excepțiile așteptate. I se vor transmite excepțiile apărute în
interiorul {try}
și în sandbox.
$loggingHandler = function (Throwable $e, Latte\Runtime\Template $template) use ($logger) {
$logger->log($e);
};
$latte = new Latte\Engine;
$latte->setExceptionHandler($loggingHandler);
Căutarea automată a layout-ului
Folosind tag-ul {layout}
,
șablonul își determină șablonul părinte. Este, de asemenea, posibil să se lase căutarea layout-ului să se facă automat,
ceea ce simplifică scrierea șabloanelor, deoarece nu va mai fi necesar să se specifice tag-ul {layout}
în ele.
Acest lucru se realizează în felul următor:
$finder = function (Latte\Runtime\Template $template) {
if (!$template->getReferenceType()) {
// returnează calea către fișierul de layout
return 'automatic.layout.latte';
}
};
$latte = new Latte\Engine;
$latte->addProvider('coreParentFinder', $finder);
Dacă șablonul nu trebuie să aibă layout, o anunță prin tag-ul {layout none}
.