Nette Documentation Preview

syntax
Загрузчики
**********
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Загрузчики

Загрузчики — это механизм, который Latte использует для получения исходного кода ваших шаблонов. Чаще всего шаблоны хранятся в виде файлов на диске, но благодаря гибкой системе загрузчиков вы можете загружать их практически откуда угодно или даже генерировать динамически.

Что такое Загрузчик?

Когда вы работаете с шаблонами, вы обычно представляете себе файлы .latte, расположенные в структуре каталогов вашего проекта. Этим занимается загрузчик по умолчанию FileLoader в Latte. Однако связь между именем шаблона (например, 'main.latte' или 'components/card.latte') и его фактическим исходным кодом не обязательно должна быть прямым отображением на путь к файлу.

Именно здесь вступают в игру загрузчики. Загрузчик — это объект, задачей которого является взять имя шаблона (идентифицирующую строку) и предоставить Latte его исходный код. Latte при выполнении этой задачи полностью полагается на настроенный загрузчик. Это относится не только к начальному шаблону, запрошенному с помощью $latte->render('main.latte'), но и к каждому шаблону, на который ссылаются внутри с помощью тегов, таких как {include ...}, {layout ...}, {embed ...} или {import ...}.

Зачем использовать пользовательский загрузчик?

  • Загрузка из альтернативных источников: Получение шаблонов, хранящихся в базе данных, в кеше (например, Redis или Memcached), в системе управления версиями (например, Git, на основе конкретного коммита) или динамически генерируемых.
  • Реализация пользовательских конвенций именования: Вы можете захотеть использовать более короткие псевдонимы для шаблонов или реализовать специфическую логику путей поиска (например, сначала искать в каталоге темы, затем вернуться к каталогу по умолчанию).
  • Добавление безопасности или контроля доступа: Пользовательский загрузчик может проверять права пользователя перед загрузкой определенных шаблонов.
  • Предварительная обработка: Хотя это обычно не рекомендуется (проходы компиляции лучше), загрузчик теоретически мог бы предварительно обработать содержимое шаблона, прежде чем передать его в Latte.

Загрузчик для экземпляра Latte\Engine устанавливается с помощью метода setLoader():

$latte = new Latte\Engine;

// Использование FileLoader по умолчанию для файлов в '/path/to/templates'
$loader = new Latte\Loaders\FileLoader('/path/to/templates');
$latte->setLoader($loader);

Загрузчик должен реализовывать интерфейс Latte\Loader.

Встроенные Загрузчики

Latte предлагает несколько стандартных загрузчиков:

FileLoader

Это загрузчик по умолчанию, используемый классом Latte\Engine, если не указан другой. Он загружает шаблоны непосредственно из файловой системы.

При желании вы можете установить корневой каталог для ограничения доступа:

use Latte\Loaders\FileLoader;

// Следующее позволит загружать шаблоны только из каталога /var/www/html/templates
$loader = new FileLoader('/var/www/html/templates');
$latte->setLoader($loader);

// $latte->render('../../../etc/passwd'); // Это выбросило бы исключение

// Рендеринг шаблона, расположенного в /var/www/html/templates/pages/contact.latte
$latte->render('pages/contact.latte');

При использовании тегов, таких как {include} или {layout}, он разрешает имена шаблонов относительно текущего шаблона, если не указан абсолютный путь.

StringLoader

Этот загрузчик получает содержимое шаблона из ассоциативного массива, где ключи — это имена шаблонов (идентификаторы), а значения — строки исходного кода шаблона. Он особенно полезен для тестирования или небольших приложений, где шаблоны могут храниться непосредственно в PHP-коде.

use Latte\Loaders\StringLoader;

$loader = new StringLoader([
	'main.latte' => 'Hello {$name}, include is below:{include helper.latte}',
	'helper.latte' => '{var $x = 10}Included content: {$x}',
	// Добавьте другие шаблоны по мере необходимости
]);

$latte->setLoader($loader);

$latte->render('main.latte', ['name' => 'World']);
// Вывод: Hello World, include is below:Included content: 10

Если вам нужно отрендерить только один шаблон непосредственно из строки без необходимости включения или наследования, ссылающихся на другие именованные строковые шаблоны, вы можете передать строку напрямую методу render() или renderToString() при использовании StringLoader без массива:

$loader = new StringLoader;
$latte->setLoader($loader);

$templateString = 'Hello {$name}!';
$output = $latte->renderToString($templateString, ['name' => 'Alice']);
// $output содержит 'Hello Alice!'

Создание пользовательского Загрузчика

Для создания пользовательского загрузчика (например, для загрузки шаблонов из базы данных, кеша, системы управления версиями или другого источника) вам необходимо создать класс, реализующий интерфейс Latte\Loader.

Давайте посмотрим, что должен делать каждый метод.

getContent(string $name)string

Это основной метод загрузчика. Его задача — получить и вернуть полный исходный код шаблона, идентифицированного с помощью $name (как передано методу $latte->render() или возвращено методом getReferredName()).

Если шаблон не может быть найден или доступ к нему невозможен, этот метод должен выбросить исключение Latte\RuntimeException.

public function getContent(string $name): string
{
	// Пример: Загрузка из гипотетического внутреннего хранилища
	$content = $this->storage->read($name);
	if ($content === null) {
		throw new Latte\RuntimeException("Template '$name' cannot be loaded.");
	}
	return $content;
}

getReferredName(string $name, string $referringName)string

Этот метод отвечает за разрешение имен шаблонов, используемых внутри тегов, таких как {include}, {layout} и т.д. Когда Latte встречает, например, {include 'partial.latte'} внутри main.latte, он вызывает этот метод с $name = 'partial.latte' и $referringName = 'main.latte'.

Задача метода — преобразовать $name в канонический идентификатор (например, абсолютный путь, уникальный ключ базы данных), который будет использоваться при вызове других методов загрузчика, на основе контекста, предоставленного в $referringName.

public function getReferredName(string $name, string $referringName): string
{
	return ...;
}

getUniqueId(string $name)string

Latte использует кеш скомпилированных шаблонов для повышения производительности. Каждый скомпилированный файл шаблона нуждается в уникальном имени, производном от идентификатора исходного шаблона. Этот метод предоставляет строку, которая однозначно идентифицирует шаблон $name.

Для шаблонов, основанных на файлах, может служить абсолютный путь. Для шаблонов в базе данных распространена комбинация префикса и ID базы данных.

public function getUniqueId(string $name): string
{
	return ...;
}

Пример: Простой Загрузчик из Базы Данных

Этот пример показывает базовую структуру загрузчика, который загружает шаблоны, хранящиеся в таблице базы данных с именем templates со столбцами name (уникальный идентификатор), content и updated_at.

use Latte;

class DatabaseLoader implements Latte\Loader
{
	public function __construct(
		private \PDO $db,
	) {
	}

	public function getContent(string $name): string
	{
		$stmt = $this->db->prepare('SELECT content FROM templates WHERE name = ?');
		$stmt->execute([$name]);
		$content = $stmt->fetchColumn();
		if ($content === false) {
			throw new Latte\RuntimeException("Template '$name' not found in database.");
		}
		return $content;
	}

	// Этот простой пример предполагает, что имена шаблонов ('homepage', 'article', и т.д.)
	// являются уникальными ID и шаблоны не ссылаются друг на друга относительно.
	public function getReferredName(string $name, string $referringName): string
	{
		return $name;
	}

	public function getUniqueId(string $name): string
	{
		// Использование префикса и самого имени здесь уникально и достаточно
		return 'db_' . $name;
	}
}

// Использование:
$pdo = new \PDO(/* детали подключения */);
$loader = new DatabaseLoader($pdo);
$latte->setLoader($loader);
$latte->render('homepage'); // Загрузит шаблон с именем 'homepage' из БД

Пользовательские загрузчики дают вам полный контроль над тем, откуда берутся ваши шаблоны Latte, что позволяет интегрироваться с различными системами хранения и рабочими процессами.