Pět novinek v Latte 3.1, které vám zpříjemní život
Latte 3.1 přináší pětici novinek – nové filtry
|column, |commas a |limit, vylepšený
|slice pro iterátory a dvě nové featury enginu. Žádná
revoluce, ale drobnosti, které oceníte.
Konec úniku proměnných z
{foreach}
Tohle mě štvalo roky. Napíšete {foreach $items as $item},
cyklus skončí, a $item vám vesele přežívá s hodnotou
posledního prvku. Horší je, když si tím přepíšete proměnnou, se kterou
jste počítali:
{var $name = 'Jupí'}
{foreach $users as $name}
...
{/foreach}
{$name} {* ouha, tady už není 'Jupí' *}
Latte vás sice odedávna varovalo, když foreach přepsal proměnnou
předanou do šablony přes parametry. Ale proměnné vytvořené přímo
v šabloně, například přes {var}, se přepisovaly tiše. A to
je přesně ten zákeřný případ.
Teď to jde vyřešit nastavením:
$latte->setFeature(Latte\Feature::ScopedLoopVariables);
Proměnné z {foreach} od teď existují jen uvnitř cyklu. Po
skončení se vrátí původní hodnota. A pokud proměnná předtím
neexistovala? Zmizí úplně.
{var $name = 'Jupí'}
{foreach $users as $name}
...
{/foreach}
{$name} {* vypíše 'Jupí', jupí! *}
A to staré varování o přepsaných parametrech? S touhle featurou se vypíná, protože přestává dávat smysl – nic se už nepřepisuje.
Funguje to i s destrukturováním {foreach $data as [$a, $b]}
a samozřejmě i s klíčem {foreach $arr as $k => $v} – po
cyklu se uklidí vše. Vnořené cykly mají nezávislé scope.
Jediná výjimka: pokud iterujete přes referenci
{foreach $arr as &$v}, scope se neuplatní – reference
přímo modifikují původní pole, takže obnovování hodnot po cyklu by je
rozbilo. Logické.
Odsazujte šablony, jak chcete
Znáte to: máte <ul> a uvnitř {foreach},
který generuje <li>. Přirozeně to odsadíte, aby šablona
byla čitelná. Jenže to odsazení se pak propíše do výstupu. Buď máte
hezký kód a ošklivý HTML, nebo naopak.
Neakceptovatelné.
S Feature::Dedent tohle dilema mizí:
$latte->setFeature(Latte\Feature::Dedent);
Latte automaticky odstraní společné odsazení uvnitř párových tagů. Takže tohle:
<ul>
{foreach $items as $item}
<li>{$item}</li>
{/foreach}
</ul>
vygeneruje:
<ul>
<li>...</li>
<li>...</li>
</ul>
Odsazení jako by tam nikdy nebylo.
A protože se dedent provádí už při kompilaci šablony, ne při každém
renderování, nemá to žádný vliv na výkon. Funguje pro všechny párové
tagy – {if}, {block}, {capture},
{foreach} a další. Vnořené tagy se dedentují nezávisle,
každý na své úrovni.
Pokud je odsazení nekonzistentní – kupříkladu mícháte tabulátory
s mezerami, nebo některý řádek nemá dostatečné odsazení – Latte
vyhodí CompileException s přesným číslem řádku. Žádné
tiché polykání chyb.
Filtr
|commas
Spojit pole do řetězce odděleného čárkami – brnkačka. Ale co když chcete před posledním prvkem napsat „a" místo čárky? To je přesně ta věc, kvůli které v šabloně začnete psát podmínky a najednou máte čtyři řádky kódu místo jednoho. Přitom chcete říct jen „jablko, hruška a švestka".
{['jablko', 'hruška', 'švestka']|commas} {* jablko, hruška, švestka *}
{['jablko', 'hruška', 'švestka']|commas:' a '} {* jablko, hruška a švestka *}
{['jablko', 'hruška', 'švestka']|commas:', nebo '} {* jablko, hruška, nebo švestka *}
Bez parametru spojí čárkou a mezerou. S parametrem použije zadaný řetězec jako oddělovač mezi posledními dvěma prvky – zbytek zůstane oddělený čárkami. Prostě čeština, ne foreach.
Filtr
|column
Máte pole záznamů o uživatelích, třeba
[['id' => 1, 'name' => 'Jan'], ['id' => 2, 'name' => 'Petr'], ...],
a potřebujete z nich dostat jen jména? Filtr |column vytáhne
hodnoty jednoho sloupce – ať už jde o klíč v poli, nebo property
objektu:
{$users|column:'name'|commas} {* Jan, Petr, Marie *}
Volitelně přijímá i druhý parametr pro indexování výsledků:
{foreach ($users|column:'name':'id') as $id => $name}
{$id}: {$name}
{/foreach}
Funguje i s iterátory, nejen s poli – nicméně iterátor se interně převede na pole, takže na žádnou lazy magii nečekejte.
Filtr
|slice pro iterátory a nový filtr |limit
Filtr |slice vyřízne kus pole nebo řetězce (u řetězců
s respektem k UTF-8). Dosud ale fungoval jen s poli a řetězci. Teď
zvládne i iterátory a generátory – vrací generátor, který čte prvky
z původního zdroje jeden po druhém a po dosažení limitu se zastaví. Celý
iterátor se do paměti nenačítá:
{foreach ($generator|slice:0:10) as $item}
{$item}
{/foreach}
A k tomu přibyl filtr
|limit – pohodlnější varianta pro typický případ
„vezmi prvních N prvků". Funguje s poli, iterátory i řetězci
(s respektem k UTF-8):
{foreach ($items|limit:5) as $item}
{$item}
{/foreach}
{$description|limit:100}
Rozdíl oproti |slice: filtr |limit ve výchozím
stavu zachovává originální klíče.
Jak na to
Nové featury ScopedLoopVariables a Dedent se
zapínají přes setFeature():
$latte = new Latte\Engine;
$latte->setFeature(Latte\Feature::ScopedLoopVariables);
$latte->setFeature(Latte\Feature::Dedent);
A pokud používáte Nette, stačí to zapnout v konfiguraci:
latte:
scopedLoopVariables: true
dedent: true
Pět drobností pro život.
Chcete-li odeslat komentář, přihlaste se