Egyéni szűrők létrehozása

A szűrők hatékony eszközök az adatok formázására és módosítására közvetlenül a Latte sablonokban. Tiszta szintaxist kínálnak a csővezeték szimbólum (|) használatával a változók vagy kifejezések eredményeinek a kívánt kimeneti formátumra történő átalakításához.

Mik azok a szűrők?

A szűrők a Latte-ban lényegében PHP függvények, amelyeket kifejezetten egy bemeneti érték kimeneti értékké alakítására terveztek. A csővezeték jelöléssel (|) alkalmazzák őket a sablon kifejezéseken ({...}) belül.

Kényelem: A szűrők lehetővé teszik a gyakori formázási feladatok (mint a dátumok formázása, kis- és nagybetűk váltása, rövidítés) vagy adatmanipulációk újrafelhasználható egységekbe való beágyazását. Ahelyett, hogy bonyolult PHP kódot ismételgetne a sablonjaiban, egyszerűen alkalmazhat egy szűrőt:

{* Bonyolult PHP helyett a rövidítéshez: *}
{$article->text|truncate:100}

{* Dátumformázó kód helyett: *}
{$event->startTime|date:'Y-m-d H:i'}

{* Több átalakítás alkalmazása: *}
{$product->name|lower|capitalize}

Olvashatóság: A szűrők használata tisztábbá és inkább a prezentációra összpontosítóvá teszi a sablonokat, mivel az átalakítási logika a szűrő definíciójába kerül át.

Kontextusérzékenység: A Latte szűrőinek kulcsfontosságú előnye, hogy képesek kontextusérzékenyek lenni. Ez azt jelenti, hogy a szűrő felismerheti a tartalom típusát, amellyel dolgozik (HTML, JavaScript, egyszerű szöveg stb.), és alkalmazhatja a megfelelő logikát vagy escapelést, ami elengedhetetlen a biztonság és a helyesség szempontjából, különösen HTML generálásakor.

Integráció az alkalmazáslogikával: Mint az egyéni függvények, a szűrő mögötti PHP callable lehet closure, statikus metódus vagy példány metódus. Ez lehetővé teszi a szűrők számára, hogy hozzáférjenek az alkalmazás szolgáltatásaihoz vagy adataihoz, ha szükséges, bár fő céljuk továbbraও a bemeneti érték átalakítása marad.

A Latte alapértelmezés szerint gazdag standard szűrőket biztosít. Az egyéni szűrők lehetővé teszik ennek a készletnek a kiterjesztését a projekt-specifikus formázásokkal és átalakításokkal.

Ha több bemeneten alapuló logikát kell végrehajtania, vagy nincs elsődleges átalakítandó értéke, valószínűleg megfelelőbb egy egyéni függvényt használni. Ha bonyolult jelölést kell generálnia vagy a sablon folyamatát kell vezérelnie, fontolja meg egy egyéni taget.

Szűrők létrehozása és regisztrálása

Több módja van az egyéni szűrők definiálásának és regisztrálásának a Latte-ban.

Közvetlen regisztráció az addFilter() segítségével

A szűrő hozzáadásának legegyszerűbb módja az addFilter() metódus használata közvetlenül a Latte\Engine objektumon. Megadja a szűrő nevét (ahogyan a sablonban használni fogják) és a megfelelő PHP callable-t.

$latte = new Latte\Engine;

// Egyszerű szűrő argumentumok nélkül
$latte->addFilter('initial', fn(string $s): string => mb_substr($s, 0, 1) . '.');

// Szűrő opcionális argumentummal
$latte->addFilter('shortify', function (string $s, int $len = 10): string {
	return mb_substr($s, 0, $len);
});

// Tömböt feldolgozó szűrő
$latte->addFilter('sum', fn(array $numbers): int|float => array_sum($numbers));

Használat a sablonban:

{$name|initial}                 {* Kiírja 'J.' ha $name 'John' *}
{$description|shortify}         {* Az alapértelmezett 10-es hosszt használja *}
{$description|shortify:50}      {* 50-es hosszt használ *}
{$prices|sum}                   {* Kiírja a $prices tömb elemeinek összegét *}

Argumentumok átadása:

A csővezeték (|) bal oldalán lévő érték mindig a szűrő függvény első argumentumaként kerül átadásra. A sablonban a kettőspont (:) után megadott paraméterek a következő argumentumokként kerülnek átadásra.

{$text|shortify:30}
// Meghívja a shortify($text, 30) PHP függvényt

Regisztráció bővítményen keresztül

A jobb szervezés érdekében, különösen újrafelhasználható szűrőkészletek létrehozásakor vagy csomagként való megosztásukkor, az ajánlott módszer a Latte bővítményben való regisztrálásuk:

namespace App\Latte;

use Latte\Extension;

class MyLatteExtension extends Extension
{
	public function getFilters(): array
	{
		return [
			'initial' => $this->initial(...),
			'shortify' => $this->shortify(...),
		];
	}

	public function initial(string $s): string
	{
		return mb_substr($s, 0, 1) . '.';
	}

	public function shortify(string $s, int $len = 10): string
	{
		return mb_substr($s, 0, $len);
	}
}

// Regisztráció
$latte = new Latte\Engine;
$latte->addExtension(new App\Latte\MyLatteExtension);

Ez a megközelítés beágyazva tartja a szűrő logikáját, és egyszerűvé teszi a regisztrációt.

Szűrőbetöltő használata

A Latte lehetővé teszi egy szűrőbetöltő regisztrálását az addFilterLoader() segítségével. Ez egyetlen callable, amelyet a Latte bármely ismeretlen szűrőnévre megkérdez a fordítás során. A betöltő visszaadja a szűrő PHP callable-ját vagy null-t.

$latte = new Latte\Engine;

// A betöltő dinamikusan hozhat létre/szerezhet be szűrő callable-okat
$latte->addFilterLoader(function (string $name): ?callable {
	if ($name === 'myLazyFilter') {
		// Képzeljünk el itt egy költséges inicializálást...
		$service = get_some_expensive_service();
		return fn($value) => $service->process($value);
	}
	return null;
});

Ezt a módszert elsősorban a nagyon költséges inicializálású szűrők lusta betöltésére szánták. Azonban a modern dependency injection gyakorlatok általában hatékonyabban kezelik a lusta szolgáltatásokat.

A szűrőbetöltők bonyolultságot adnak hozzá, és általában nem ajánlottak a közvetlen regisztrációval szemben az addFilter() vagy a bővítményen belüli getFilters() segítségével. Csak akkor használjon betöltőket, ha súlyos, specifikus oka van a szűrők inicializálásával kapcsolatos teljesítményproblémákra, amelyeket másképp nem lehet megoldani.

Szűrők osztály használatával attribútumokkal

Egy másik elegáns módja a szűrők definiálásának a metódusok használata a sablon paraméter osztályában. Csak adjon hozzá egy #[Latte\Attributes\TemplateFilter] attribútumot a metódushoz.

use Latte\Attributes\TemplateFilter;

class TemplateParameters
{
	public function __construct(
		public string $description,
		// további paraméterek...
	) {}

	#[TemplateFilter]
	public function shortify(string $s, int $len = 10): string
	{
		return mb_substr($s, 0, $len);
	}
}

// Objektum átadása a sablonnak
$params = new TemplateParameters(description: '...');
$latte->render('template.latte', $params);

A Latte automatikusan felismeri és regisztrálja az ezzel az attribútummal megjelölt metódusokat, amikor a TemplateParameters objektumot átadják a sablonnak. A szűrő neve a sablonban ugyanaz lesz, mint a metódus neve (shortify ebben az esetben).

{* A paraméter osztályban definiált szűrő használata *}
{$description|shortify:50}

Kontextusérzékeny szűrők

Néha egy szűrőnek több információra van szüksége, mint csak a bemeneti érték. Szüksége lehet tudni a string tartalomtípusát, amellyel dolgozik (pl. HTML, JavaScript, egyszerű szöveg), vagy akár módosítani is azt. Ez a helyzet a kontextusérzékeny szűrők esetében.

Egy kontextusérzékeny szűrő ugyanúgy definiálódik, mint egy normál szűrő, de az első paraméterének Latte\Runtime\FilterInfo típusúnak kell lennie. A Latte automatikusan felismeri ezt az aláírást, és a szűrő hívásakor átadja a FilterInfo objektumot. A következő paraméterek a szűrő argumentumait kapják meg a szokásos módon.

use Latte\Runtime\FilterInfo;
use Latte\ContentType;

$latte->addFilter('money', function (FilterInfo $info, float $amount): string {
	// 1. Ellenőrizze a bemeneti tartalomtípust (opcionális, de ajánlott)
	//    Engedélyezze a null-t (változó bemenet) vagy az egyszerű szöveget. Utasítsa el, ha HTML-re stb. alkalmazzák.
	if (!in_array($info->contentType, [null, ContentType::Text], true)) {
		$actualType = $info->contentType ?? 'mixed';
		throw new \RuntimeException(
			"A |money szűrő inkompatibilis tartalomtípusban ($actualType) lett használva. Szöveg vagy null volt elvárva."
		);
	}

	// 2. Végezze el az átalakítást
	$formatted = number_format($amount, 2, '.', ',') . ' EUR';
	$htmlOutput = '<i>' . htmlspecialchars($formatted) . '</i>'; // Biztosítsa a helyes escapelést!

	// 3. Deklarálja a kimeneti tartalomtípust
	$info->contentType = ContentType::Html;

	// 4. Adja vissza az eredményt
	return $htmlOutput;
});

A $info->contentType egy string konstans a Latte\ContentType-ból (pl. ContentType::Html, ContentType::Text, ContentType::JavaScript stb.) vagy null, ha a szűrőt egy változóra alkalmazzák ({$var|filter}). Ezt az értéket olvashatja, hogy ellenőrizze a bemeneti kontextust, és írhatja bele, hogy deklarálja a kimeneti kontextus típusát.

A tartalomtípus HTML-re állításával közli a Latte-val, hogy a szűrő által visszaadott string biztonságos HTML. A Latte ezután nem alkalmazza erre az eredményre az alapértelmezett automatikus escapelést. Ez elengedhetetlen, ha a szűrő HTML jelölést generál.

Ha a szűrő HTML-t generál, Ön felelős a benne használt bármely bemeneti adat helyes escapeléséért (mint a fenti htmlspecialchars($formatted) hívás esetén). Ennek elmulasztása XSS sebezhetőségeket hozhat létre. Ha a szűrő csak egyszerű szöveget ad vissza, nem kell beállítania a $info->contentType-t.

Szűrők blokkokon

Minden blokkokra alkalmazott szűrőnek kontextusérzékenynek kell lennie. Ez azért van, mert a blokk tartalmának van egy definiált tartalomtípusa (általában HTML), amelyről a szűrőnek tudnia kell.

{block heading|money}1000{/block}
{* A 'money' szűrő a '1000'-et kapja második argumentumként
   és a $info->contentType ContentType::Html lesz *}

A kontextusérzékeny szűrők erőteljes vezérlést biztosítanak az adatok feldolgozása felett azok kontextusa alapján, lehetővé téve a fejlett funkciókat és biztosítva a helyes escapelési viselkedést, különösen HTML tartalom generálásakor.

verzió: 3.0