Nette Documentation Preview

syntax
Loaders
*******
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Loaders

Loaders са механизмът, който Latte използва за получаване на изходния код на вашите шаблони. Най-често шаблоните се съхраняват като файлове на диска, но благодарение на гъвкавата система на loaders, можете да ги зареждате практически отвсякъде или дори да ги генерирате динамично.

Какво е Loader?

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

Точно тук влизат в игра loaders. Loader е обект, който има за задача да вземе името на шаблона (идентифициращ низ) и да предостави на Latte неговия изходен код. Latte напълно разчита на конфигурирания loader за тази задача. Това важи не само за първоначалния шаблон, изискан с помощта на $latte->render('main.latte'), но и за всеки шаблон, рефериран вътре с помощта на тагове като {include ...}, {layout ...}, {embed ...} или {import ...}.

Защо да използвате персонализиран loader?

  • Зареждане от алтернативни източници: Получаване на шаблони, съхранени в база данни, в кеш (като Redis или Memcached), в система за управление на версии (като Git, въз основа на конкретен commit) или динамично генерирани.
  • Имплементиране на персонализирани конвенции за именуване: Може да искате да използвате по-кратки псевдоними за шаблони или да имплементирате специфична логика за пътища за търсене (напр. първо търсене в директорията на темата, след това връщане към директорията по подразбиране).
  • Добавяне на сигурност или контрол на достъпа: Персонализиран loader може да провери потребителските права преди зареждане на определени шаблони.
  • Предварителна обработка: Въпреки че това обикновено не се препоръчва (компилационните проходи са по-добри), loader би могъл теоретично да извърши предварителна обработка на съдържанието на шаблона, преди да го предаде на Latte.

Loader за инстанция на Latte\Engine се задава с помощта на метода setLoader():

$latte = new Latte\Engine;

// Използване на FileLoader по подразбиране за файлове в '/path/to/templates'
$loader = new Latte\Loaders\FileLoader('/path/to/templates');
$latte->setLoader($loader);

Loader трябва да имплементира интерфейса Latte\Loader.

Вградени Loaders

Latte предлага няколко стандартни loaders:

FileLoader

Това е loader-ът по подразбиране, използван от класа 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

Този loader получава съдържанието на шаблона от асоциативен масив, където ключовете са имената на шаблоните (идентификатори), а стойностите са низове с изходния код на шаблона. Той е особено полезен за тестване или малки приложения, където шаблоните могат да бъдат съхранени директно в 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!'

Създаване на персонализиран Loader

За да създадете персонализиран loader (напр. за зареждане на шаблони от база данни, кеш, система за управление на версии или друг източник), трябва да създадете клас, който имплементира интерфейса Latte\Loader.

Нека разгледаме какво трябва да прави всеки метод.

getContent(string $name)string

Това е основният метод на loader-а. Неговата задача е да получи и върне пълния изходен код на шаблона, идентифициран чрез $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 на каноничен идентификатор (напр. абсолютен път, уникален ключ на база данни), който ще бъде използван при извикване на други методи на loader-а, въз основа на контекста, предоставен в $referringName.

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

getUniqueId(string $name)string

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

За шаблони, базирани на файлове, може да послужи абсолютният път. За шаблони в база данни е обичайна комбинация от префикс и ID на базата данни.

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

Пример: Прост Loader за база данни

Този пример показва основната структура на loader, който зарежда шаблони, съхранени в таблица на база данни, наречена 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("Шаблон '$name' не е намерен в базата данни.");
		}
		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' от БД

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