Rozšiřování Latte

Latte je navrženo s ohledem na rozšiřitelnost. Přestože jeho standardní sada tagů, filtrů a funkcí pokrývá mnoho případů použití, často potřebujete přidat vlastní specifickou logiku nebo pomocné nástroje. Tato stránka poskytuje přehled způsobů, jak rozšířit Latte tak, aby dokonale odpovídalo požadavkům vašeho projektu – od jednoduchých pomocníků až po komplexní novou syntaxi.

Způsoby rozšíření Latte

Zde je rychlý přehled hlavních způsobů, jak můžete přizpůsobit a rozšířit Latte:

  • Vlastní filtry: Pro formátování nebo transformaci dat přímo ve výstupu šablony (např. {$var|myFilter}). Ideální pro úlohy jako formátování datumů, úpravy textu nebo aplikování specifického escapování. Můžete je také použít k úpravě větších bloků HTML obsahu tak, že obsah obalíte anonymním {block} a aplikujete na něj vlastní filtr.
  • Vlastní funkce: Pro přidání znovupoužitelné logiky, kterou lze volat v rámci výrazů v šabloně (např. {myFunction($arg1, $arg2)}). Užitečné pro výpočty, přístup k pomocným funkcím aplikace nebo generování malých částí obsahu.
  • Vlastní tagy: Pro vytváření zcela nových jazykových konstrukcí ({mytag}...{/mytag} nebo n:mytag). Tagy nabízejí nejvíce možností, umožňují definovat vlastní struktury, řídit parsování šablony a implementovat komplexní vykreslovací logiku.
  • Kompilační průchody: Funkce, které upravují abstraktní syntaktický strom (AST) šablony po parsování, ale před generováním PHP kódu. Používají se pro pokročilé optimalizace, bezpečnostní kontroly (jako je Sandbox) nebo automatické úpravy kódu.
  • Vlastní loadery: Pro změnu způsobu, jakým Latte vyhledává a načítá soubory šablon (např. načítání z databáze, šifrovaného úložiště atd.).

Výběr správné metody rozšíření je klíčový. Než vytvoříte složitý tag, zvažte, zda by nestačil jednodušší filtr nebo funkce. Ukažme si to na příkladu: implementace generátoru Lorem ipsum, který jako argument přijímá počet slov k vygenerování.

  • Jako tag? {lipsum 40} – Možné, ale tagy jsou vhodnější pro řídicí struktury nebo generování složitých značek. Tagy nelze použít přímo ve výrazech.
  • Jako filtr? {=40|lipsum} – Technicky to funguje, ale filtry jsou určeny k transformaci vstupní hodnoty. Zde je 40 argument, nikoli hodnota, která se transformuje. To působí sémanticky nesprávně.
  • Jako funkce? {lipsum(40)} – Toto je nejpřirozenější řešení! Funkce přijímají argumenty a vracejí hodnoty, což je ideální pro použití v libovolném výrazu: {var $text = lipsum(40)}.

Obecné doporučení: Používejte funkce pro výpočty/generování, filtry pro transformaci a tagy pro nové jazykové konstrukce nebo složité značky. Průchody používejte pro manipulaci s AST a loadery pro získávání šablon.

Přímá registrace

Pro pomocné nástroje specifické pro projekt nebo rychlá rozšíření umožňuje Latte přímou registraci filtrů a funkcí do objektu Latte\Engine.

Pro registraci filtru použijte metodu addFilter(). Prvním argumentem vaší filtrační funkce bude hodnota před znakem | a následující argumenty jsou ty, které se předávají za dvojtečkou :.

$latte = new Latte\Engine;

// Definice filtru (volatelný objekt: funkce, statická metoda atd.)
$myTruncate = fn(string $s, int $length = 50) => mb_substr($s, 0, $length);

// Registrace
$latte->addFilter('truncate', $myTruncate);

// Použití v šabloně: {$text|truncate} nebo {$text|truncate:100}

Můžete také zaregistrovat Filter Loader, funkci, která dynamicky poskytuje volatelné objekty filtrů podle požadovaného názvu:

$latte->addFilterLoader(fn(string $name) => /* vrátí volatelný objekt nebo null */);

Pro registraci funkce použitelné ve výrazech šablony použijte addFunction().

$latte = new Latte\Engine;

// Definice funkce
$isWeekend = fn(DateTimeInterface $date) => $date->format('N') >= 6;

// Registrace
$latte->addFunction('isWeekend', $isWeekend);

// Použití v šabloně: {if isWeekend($myDate)}Víkend!{/if}

Více informací najdete v části Vytváření vlastních filtrů a Funkcí.

Robustní způsob: Latte Extension

Zatímco přímá registrace je jednoduchá, standardním a doporučeným způsobem, jak zabalit a distribuovat rozšíření Latte, je prostřednictvím tříd Extension. Extension slouží jako centrální konfigurační bod pro registraci více tagů, filtrů, funkcí, kompilačních průchodů a dalších prvků.

Proč používat Extensions?

  • Organizace: Udržuje související rozšíření (tagy, filtry atd. pro konkrétní funkci) pohromadě v jedné třídě.
  • Znovupoužitelnost a sdílení: Snadno zabalíte svá rozšíření pro použití v jiných projektech nebo pro sdílení s komunitou (např. přes Composer).
  • Plná síla: Vlastní tagy a kompilační průchody lze registrovat pouze prostřednictvím Extensions.

Registrace Extension

Extension se registruje v Latte pomocí metody addExtension() (nebo prostřednictvím konfiguračního souboru):

$latte = new Latte\Engine;
$latte->addExtension(new MyProjectExtension);

Pokud zaregistrujete více rozšíření a ta definují stejně pojmenované tagy, filtry nebo funkce, má přednost naposledy přidané rozšíření. To také znamená, že vaše rozšíření mohou přepsat nativní tagy/filtry/funkce.

Kdykoli provedete změnu ve třídě a není vypnuté automatické obnovení, Latte automaticky překompiluje vaše šablony.

Vytvoření Extension

Pro vytvoření vlastního rozšíření potřebujete vytvořit třídu, která dědí z Latte\Extension. Pro představu, jak takové rozšíření vypadá, podívejte se na vestavěné CoreExtension.

Podívejme se na metody, které můžete implementovat:

beforeCompile (Latte\Engine $engine)void

Volá se před kompilací šablony. Metodu lze použít například pro inicializace související s kompilací.

getTags(): array

Volá se při kompilaci šablony. Vrací asociativní pole název tagu ⇒ volatelný objekt, což jsou funkce pro parsování tagů. Více informací.

public function getTags(): array
{
	return [
		'foo' => FooNode::create(...),
		'bar' => BarNode::create(...),
		'n:baz' => NBazNode::create(...),
		// ...
	];
}

Tag n:baz představuje čistý n:atribut, tedy tag, který lze zapsat pouze jako atribut.

U tagů foo a bar Latte automaticky rozpozná, zda jde o párové tagy, a pokud ano, lze je automaticky zapisovat pomocí n:atributů, včetně variant s předponami n:inner-foo a n:tag-foo.

Pořadí vykonávání takových n:atributů je určeno jejich pořadím v poli vráceném metodou getTags(). Takže n:foo je vždy proveden před n:bar, i když jsou atributy v HTML tagu uvedeny v opačném pořadí jako <div n:bar="..." n:foo="...">.

Pokud potřebujete určit pořadí n:atributů napříč více rozšířeními, použijte pomocnou metodu order(), kde parametr before xor after určuje, které tagy jsou řazeny před nebo za tagem.

public function getTags(): array
{
	return [
		'foo' => self::order(FooNode::create(...), before: 'bar'),
		'bar' => self::order(BarNode::create(...), after: ['block', 'snippet']),
	];
}

getPasses(): array

Volá se při kompilaci šablony. Vrací asociativní pole název průchodu ⇒ volatelný objekt, což jsou funkce představující tzv. kompilační průchody, které procházejí a upravují AST.

I zde lze použít pomocnou metodu order(). Hodnota parametrů before nebo after může být * s významem před/po všech.

public function getPasses(): array
{
	return [
		'optimize' => Passes::optimizePass(...),
		'sandbox' => self::order($this->sandboxPass(...), before: '*'),
		// ...
	];
}

beforeRender (Latte\Engine $engine)void

Volá se před každým vykreslením šablony. Metoda může být použita například k inicializaci proměnných používaných během vykreslování.

getFilters(): array

Volá se před vykreslením šablony. Vrací filtry jako asociativní pole název filtru ⇒ volatelný objekt. Více informací.

public function getFilters(): array
{
	return [
		'batch' => $this->batchFilter(...),
		'trim' => $this->trimFilter(...),
		// ...
	];
}

getFunctions(): array

Volá se před vykreslením šablony. Vrací funkce jako asociativní pole název funkce ⇒ volatelný objekt. Více informací.

public function getFunctions(): array
{
	return [
		'clamp' => $this->clampFunction(...),
		'divisibleBy' => $this->divisibleByFunction(...),
		// ...
	];
}

getProviders(): array

Volá se před vykreslením šablony. Vrací pole poskytovatelů, což jsou obvykle objekty, které používají tagy za běhu. Přistupuje se k nim přes $this->global->.... Více informací.

public function getProviders(): array
{
	return [
		'myFoo' => $this->foo,
		'myBar' => $this->bar,
		// ...
	];
}

getCacheKey (Latte\Engine $engine)mixed

Volá se před vykreslením šablony. Návratová hodnota se stává součástí klíče, jehož hash je obsažen v názvu souboru kompilované šablony. Pro různé návratové hodnoty tedy Latte vygeneruje různé cache soubory.

verze: 3.0 2.x