Novinka v Latte: filtr |group

- David Grudl
- Nette Core | 8285
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}