Novinka v Latte: filtr |group
- David Grudl
- Nette Core | 8215
Přidal jsem do Latte velmi užitečný filtr, který mi připadá jako
srozumitelnější alternativa pro {iteratewhile}. Jde
o filtr |group
.
Princip je úplně prostý: data, která vypisuju, si seskupím podle nějakého klíče.
Jako příklad si vezmu tuto tabulku, kterou pojmenuju
things
:
id | categoryId | name |
---|---|---|
1 | 1 | Apple |
2 | 1 | Banana |
3 | 2 | PHP |
4 | 3 | Green |
5 | 3 | Red |
6 | 3 | Blue |
kterou chci při výpisu pomocí foreach seskupit podle kategorií:
<ul>
<li>Apple</li>
<li>Banana</li>
</ul>
<ul>
<li>PHP</li>
</ul>
<ul>
<li>Green</li>
<li>Red</li>
<li>Blue</li>
</ul>
Pro porovnání sem dávám řešení pomocí
{iterateWhile}
:
{foreach $things as $item}
<ul>
{iterateWhile}
<li>{$item->name}</li>
{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
</ul>
{/foreach}
A teď totéž pomocí group (demo)
{foreach ($things|group: categoryId) as $categoryId => $items}
<ul>
{foreach $items as $item}
<li>{$item->name}</li>
{/foreach}
</ul>
{/foreach}
Group vrátí pole polí, kde klíčem bude právě hodnota
categoryId
.
Hlavní rozdíl oproti iterateWhile
je ten, že
group
zpracuje celý vstup a pak vrátí seskupený výsledek,
zatímco při iterateWhile
se data iterují postupně. Group proto
nevadí, když kategorie nepůjdou ve vstupních datech postupně. Na výstupu
pak budou v pořadí, v jakém se postupně objevily v datech.
Spojení s Nette Database
Zajímavě se dá využít při spojení s Nette Database. Máme tedy
tabulku things
a ta je přes sloupec categoryId
propojena s tabulkou categories
:
categoryId | name |
---|---|
1 | Fruits |
2 | Languages |
3 | Colors |
Pomocí Nette Database Explorer vytáhnu z tabulky data pomocí
$things = $db->table('things')
. A jak známo, během iterace
mohu přistupovat nejen k položkám $item->name
a
$item->categoryId
, ale také rovnou do připojené tabulky přes
$item->category->name
. A právě podle
$item->category
budu data seskupovat:
{foreach ($things|group: category) as $category => $items}
<h1>{$category->name}</h1>
<ul>
{foreach $items as $item}
<li>{$item->name}</li>
{/foreach}
</ul>
{/foreach}
Vyměnil jsem group: categoryId
za group: category
,
takže v klíči teď není číslo, ale řádek v odkazované tabulce.
A data z něj můžu pohodlně vypsat jako
{$category->name}
.
Vnořené smyčky
V příkladu interateWhile je ukázka i vnořené smyčky, tedy seskupování podle podkategorií. Totéž se dá samozřejmě udělat i s group:
{foreach ($things|group: categoryId) as $categoryId => $items1}
<ul>
{foreach ($items1|group: subcategoryId) as $items2}
<ol>
{foreach $items2 as $item}
<li>{$item->name}
{/foreach}
</ol>
{/foreach}
</ul>
{/foreach}