Практики за разработчици
Инсталиране
Най-добрият начин за инсталиране на Latte е да се използва Composer:
composer require latte/latte
Поддържани версии на PHP (важи за последните версии на Latte):
версия | съвместима с PHP |
---|---|
Latte 3.0 | PHP 8.0 – 8.2 |
Как да визуализирате шаблон
Как да визуализираме шаблон? Просто използвайте този прост код:
$latte = new Latte\Engine;
// директория за кеш
$latte->setTempDirectory('/path/to/tempdir');
$params = [ /* template variables */ ];
// или $params = new TemplateParameters(/* ... */);
// визуализиране на изхода
$latte->render('template.latte', $params);
// или извеждане на променлива
$output = $latte->renderToString('template.latte', $params);
Параметрите могат да бъдат масиви или още по-добре обекти, което ще осигури проверка на типа и предлагане в редактора.
Можете да намерите и примери за използване в хранилището Latte examples.
Производителност и кеширане
Шаблоните на Latte са изключително бързи, тъй като Latte ги компилира директно в PHP код и ги кешира на диска. По този начин те нямат допълнителни разходи в сравнение с шаблоните, написани на чист PHP.
Кешът се възстановява автоматично при всяка промяна на изходния файл. Така че можете удобно да редактирате своите Latte шаблони по време на разработката и да виждате промените веднага в браузъра. Можете да деактивирате тази функция в производствена среда и да спестите малко производителност:
$latte->setAutoRefresh(false);
Когато се внедрява в производствен сървър, първоначалното генериране на кеш, особено за по-големи приложения, може да отнеме известно време. Latte има вградена превенция срещу “препускане на кеша:https://en.wikipedia.org/…che_stampede”. Това е ситуация, при която сървърът получава голям брой едновременни заявки и тъй като кешът на Latte все още не съществува, всички те ще го генерират едновременно. Което води до скок на процесора. Latte е умен и когато има няколко едновременни заявки, само първата нишка генерира кеша, а останалите изчакват и след това го използват.
Параметри като клас
По-добре от подаването на променливи към шаблона като масиви е да се създаде клас. Получавате безопасен за типа запис, хубаво предложение в IDE и начин да регистрирате филтри и функции.
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,
));
Деактивиране на автоматичното избягване на променлива
Ако променливата съдържа HTML низ, можете да я маркирате така, че Latte да
не я извежда автоматично (и следователно двойно). По този начин се
избягва необходимостта от посочване на |noescape
в шаблона.
Най-лесният начин е да обвиете низа в обект Latte\Runtime\Html
:
$params = [
'articleBody' => new Latte\Runtime\Html($article->htmlBody),
];
Latte също така не избягва всички обекти, които имплементират
интерфейса Latte\HtmlStringable
. Така че можете да създадете свой
собствен клас, чийто метод __toString()
ще връща HTML код, който няма да
бъде ескапиран автоматично:
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'),
];
Методът __toString
трябва да връща коректен HTML код и да
осигурява ескапиране на параметрите, в противен случай може да
възникне XSS уязвимост!
Как да разширим Latte с помощта на филтри, етикети и др.
Как да добавите потребителски филтър, функция, таг и т.н. в Latte? Научете това в главата Разширяване на Latte. Ако искате да използвате повторно промените си в различни проекти или ако искате да ги споделите с други хора, тогава трябва да създадете разширение.
Всеки код в шаблона {php ...}
Във вътрешността на символа могат да се записват само PHP изрази {do}
таг, така че не можете например да
вмъквате конструкции като if ... else
или изречения, завършващи с
точка и запетая.
Можете обаче да регистрирате разширението RawPhpExtension
, което
добавя тага {php ...}
. Можете да го използвате, за да вмъкнете
какъвто и да е PHP код. То не подлежи на никакви правила за режим на
пясъчник, така че използването му е отговорност на автора на шаблона.
$latte->addExtension(new Latte\Essential\RawPhpExtension);
Проверка на генерирания код
Latte компилира шаблоните в PHP код. Разбира се, той гарантира, че генерираният код е синтактично валиден. Въпреки това, когато използвате разширения на трети страни или RawPhpExtension, Latte не може да гарантира коректността на генерирания файл. Също така в PHP можете да напишете код, който е синтактично правилен, но е забранен (например присвояване на стойност на променливата $this) и предизвиква грешка при компилиране на PHP. Ако напишете такава операция в шаблон, тя ще бъде включена и в генерирания PHP код. Тъй като в PHP има над двеста различни забранени операции, Latte няма за цел да ги открива. Самият PHP ще ги маркира при визуализиране, което обикновено не е проблем.
Има обаче ситуации, в които искате да знаете по време на компилирането на шаблона, че той не съдържа грешки при компилирането на PHP. Особено когато шаблоните могат да бъдат редактирани от потребители или използвате Sandbox. В такъв случай нека шаблоните се проверяват по време на компилирането. Можете да активирате тази функционалност, като използвате метода Engine::enablePhpLint(). Тъй като за проверката трябва да се извика двоичната програма на PHP, подайте пътя до нея като параметър:
$latte = new Latte\Engine;
$latte->enablePhpLinter('/path/to/php');
try {
$latte->compile('home.latte');
} catch (Latte\CompileException $e) {
// улавя грешки на Latte, а също и грешка при компилиране в PHP
echo 'Error: ' . $e->getMessage();
}
Местоположение
Latte ви позволява да зададете локала, който влияе на форматирането на
числата, датите и сортирането. Той се задава чрез метода setLocale()
.
Идентификаторът на локала следва стандарта за езикови маркери на IETF,
който използва разширението на PHP intl
. Той се състои от код на
езика и евентуално от код на страната, например en_US
за английски
език в САЩ, de_DE
за немски език в Германия и т.н.
$latte = new Latte\Engine;
$latte->setLocale('cs');
Настройката на локала влияе на филтрите localDate, sort, number и bytes.
Изисква разширението PHP intl
. Настройката в Latte не влияе
на глобалната настройка на локала в PHP.
Строг режим
В режим на стриктно анализиране Latte проверява за липсващи затварящи
HTML тагове и също така забранява използването на променливата
$this
. За да го включите:
$latte = new Latte\Engine;
$latte->setStrictParsing();
За да генерирате шаблони със заглавие declare(strict_types=1)
, направете
следното:
$latte = new Latte\Engine;
$latte->setStrictTypes();
Превод в шаблони
Използвайте разширението TranslatorExtension
, за да добавите {_...}
, {translate}
и да филтрирате translate
към шаблона. Те се
използват за превод на стойности или части от шаблона на други езици.
Параметърът е методът (извикващ се на PHP), който извършва превода:
class MyTranslator
{
public function __construct(private string $lang)
{}
public function translate(string $original): string
{
// създаване на $translated от $original в съответствие с $this->lang
return $translated;
}
}
$translator = new MyTranslator($lang);
$extension = new Latte\Essential\TranslatorExtension(
$translator->translate(...), // [$translator, 'translate'] в PHP 8.0
);
$latte->addExtension($extension);
Преводачът се извиква по време на изпълнение, когато шаблонът се визуализира. Въпреки това Latte може да превежда всички статични текстове по време на компилирането на шаблона. Това спестява производителност, тъй като всеки низ се превежда само веднъж и полученият превод се записва в компилирания файл. По този начин се създават няколко компилирани версии на шаблона в кеш директорията, по една за всеки език. За да направите това, трябва само да посочите езика като втори параметър:
$extension = new Latte\Essential\TranslatorExtension(
$translator->translate(...),
$lang,
);
Под статичен текст разбираме например {_'hello'}
или
{translate}hello{/translate}
. Нестатичният текст, като например {_$foo}
,
ще продължи да се превежда по време на изпълнение.
Шаблонът може също така да предава допълнителни параметри на
преводача чрез {_$original, foo: bar}
или {translate foo: bar}
, които той
получава като масив $params
:
public function translate(string $original, ...$params): string
{
// $params['foo'] === 'bar'
}
Отстраняване на грешки и Tracy
Latte се опитва да направи разработката възможно най-приятна. За целите
на отстраняването на грешки има три тага {dump}
, {debugbreak}
и {trace}
.
Най-голямо удобство ще получите, ако инсталирате чудесния инструмент за отстраняване на грешки Tracy и активирате приставката Latte:
// дава възможност на Tracy
Tracy\Debugger::enable();
$latte = new Latte\Engine;
// активира разширението на Трейси
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);
Сега ще виждате всички грешки в чист червен екран, включително грешки в шаблони с подчертаване на редове и колони(видео). В същото време в долния десен ъгъл в така наречения Tracy Bar се появява таб за Latte, в който можете ясно да видите всички визуализирани шаблони и техните връзки (включително възможност за щракване в шаблона или компилирания код), както и променливите:
Тъй като Latte компилира шаблоните в четлив PHP код, можете удобно да ги преглеждате във вашата IDE.
Linter: Проверяване на синтаксиса на шаблона
Инструментът Linter ще ви помогне да преминете през всички шаблони и да проверите за грешки в синтаксиса. Той се стартира от конзолата:
vendor/bin/latte-lint <path>
Използвайте параметъра --strict
, за да активирате строг режим.
Ако използвате потребителски тагове, създайте и свой персонализиран
Linter, например custom-latte-lint
:
#!/usr/bin/env php
<?php
// въведете действителния път до файла autoload.php
require __DIR__ . '/vendor/autoload.php';
$path = $argv[1] ?? '.';
$linter = new Latte\Tools\Linter;
$latte = $linter->getEngine();
// добавете индивидуалните си разширения тук
$latte->addExtension(/* ... */);
$ok = $linter->scanDirectory($path);
exit($ok ? 0 : 1);
Като алтернатива можете да предадете свой собствен обект
Latte\Engine
на Linter:
$latte = new Latte\Engine;
// тук конфигурираме обекта $latte
$linter = new Latte\Tools\Linter(engine: $latte);
Зареждане на шаблони от низ
Трябва да зареждате шаблони от низове вместо от файлове, може би за целите на тестването? StringLoader ще ви помогне:
$latte->setLoader(new Latte\Loaders\StringLoader([
'main.file' => '{include other.file}',
'other.file' => '{if true} {$var} {/if}',
]));
$latte->render('main.file', $params);
Обработчик на изключения
Можете да дефинирате свой собствен манипулатор за очакваните
изключения. Изключенията, повдигнати вътре {try}
и в пясъчника се предават към него.
$loggingHandler = function (Throwable $e, Latte\Runtime\Template $template) use ($logger) {
$logger->log($e);
};
$latte = new Latte\Engine;
$latte->setExceptionHandler($loggingHandler);
Автоматично търсене на оформление
Използване на тага {layout}
, шаблонът
определя своя родителски шаблон. Възможно е също така макетът да се
търси автоматично, което ще опрости писането на шаблони, тъй като няма
да е необходимо те да включват тага {layout}
.
Това се постига по следния начин:
$finder = function (Latte\Runtime\Template $template) {
if (!$template->getReferenceType()) {
// връща пътя до родителския файл на шаблона
return 'automatic.layout.latte';
}
};
$latte = new Latte\Engine;
$latte->addProvider('coreParentFinder', $finder);
Ако шаблонът не трябва да има оформление, той ще посочи това с тага
{layout none}
.