Практика для розробників

Інсталяція

Найкращим способом встановлення Latte є використання Composer:

composer require latte/latte

Підтримувані версії PHP (стосується останніх версій Latte з патчем):

версія сумісна з PHP
Latte 3.0 PHP 8.0 – 8.2
Latte 2.11 PHP 7.1 – 8.2
Latte 2.8 – 2.10 PHP 7.1 – 8.1

Як відрендерити шаблон

Як відрендерити шаблон? Просто використовуйте цей простий код:

$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. Якщо ви хочете повторно використовувати ваші зміни у різних проектах або поділитися ними з іншими, вам слід створити розширення.

Будь-який код у шаблоні {php ...}

Усередині тегу PHP можна писати тільки PHP-вирази, тому ви не можете вставляти в нього конструкції, що закінчуються комою. {do} тому ви не можете, наприклад, вставляти конструкції на кшталт if ... else або оператори, що закінчуються крапкою з комою.

Однак ви можете зареєструвати розширення RawPhpExtension, яке додає тег {php ...}, який можна використовувати для вставки будь-якого PHP-коду на ризик автора шаблону.

$latte->addExtension(new Latte\Essential\RawPhpExtension);

Переклад у шаблонах

Використовуйте розширення 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'
}

Налагодження та трейси

Latte намагається зробити розробку якомога приємнішою. Для налагодження існують три теги {dump}, {debugbreak} і {trace}.

Ви отримаєте максимальний комфорт, якщо встановите чудовий інструмент для налагодження Tracy і активуєте плагін Latte:

// вмикає Tracy
Tracy\Debugger::enable();

$latte = new Latte\Engine;
// активує розширення Tracy
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);

Тепер ви побачите всі помилки на акуратному червоному екрані, включаючи помилки в шаблонах з підсвічуванням рядків і стовпців(відео). При цьому в правому нижньому куті в так званому Tracy Bar з'являється вкладка для Latte, де ви можете чітко бачити всі відрендеринговані шаблони і їх взаємозв'язки (в тому числі з можливістю кліка в шаблон або скомпільований код), а також змінні:

Оскільки Latte компілює шаблони в читабельний PHP-код, ви можете зручно переміщатися по ним у вашій IDE.

Linter: Перевірка синтаксису шаблону

Інструмент Linter допоможе вам переглянути всі шаблони і перевірити їх на наявність синтаксичних помилок. Він запускається з консолі:

vendor/bin/latte-lint <path>

Якщо ви використовуєте кастомні теги, також створіть свій власний Linter, наприклад, custom-latte-lint:

#!/usr/bin/env php
<?php

// вкажіть фактичний шлях до файлу autoload.php
require __DIR__ . '/vendor/autoload.php';

$linter = new Latte\Tools\Linter($engine);
$linter->scanDirectory($path);

$engine = new Latte\Engine;
// прописує тут окремі розширення
$engine->addExtension(/* ... */);

$path = $argv[1];
$linter = new Latte\Tools\Linter(engine: $engine);
$ok = $linter->scanDirectory($path);
exit($ok ? 0 : 1);

Завантаження шаблонів з рядка

Потрібно завантажити шаблони з рядків, а не з файлів, можливо, для тестування? 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}.