Vse, kar ste vedno želeli vedeti o združevanju v skupine
Pri delu s podatki v predlogah pogosto naletite na potrebo po njihovem združevanju v skupine ali posebnem prikazu glede na določena merila. V ta namen Latte ponuja več zmogljivih orodij.
Filter in funkcija |group
omogočata učinkovito grupiranje podatkov na podlagi določenih meril, filter
|batch
olajša razdelitev podatkov v fiksne serije, oznaka {iterateWhile}
pa ponuja možnost
kompleksnejšega cikličnega nadzora s pogoji. Vsaka od teh oznak ponuja posebne možnosti za delo s podatki, zaradi česar sta
nepogrešljivi orodji za dinamičen in strukturiran prikaz informacij v predlogah Latte.
Filter in funkcija group
Predstavljajte si tabelo podatkovne zbirke items
s predmeti, razdeljenimi v kategorije:
id | categoryId | name |
---|---|---|
1 | 1 | Apple |
2 | 1 | Banana |
3 | 2 | PHP |
4 | 3 | zelena |
5 | 3 | rdeča |
6 | 3 | Modra |
Preprost seznam vseh elementov s predlogo Latte bi bil videti takole:
<ul>
{foreach $items as $item}
<li>{$item->name}</li>
{/foreach}
</ul>
Če pa bi želeli, da so predmeti razvrščeni v skupine po kategorijah, jih moramo razdeliti tako, da ima vsaka kategorija svoj seznam. Rezultat bi bil potem videti takole:
<ul>
<li>Apple</li>
<li>Banana</li>
</ul>
<ul>
<li>PHP</li>
</ul>
<ul>
<li>Green</li>
<li>Red</li>
<li>Blue</li>
</ul>
Nalogo lahko enostavno in elegantno rešimo z uporabo spletne strani |group
. Kot parameter navedemo
categoryId
, kar pomeni, da bodo elementi razdeljeni v manjša polja na podlagi vrednosti
$item->categoryId
(če bi bil $item
polje, bi uporabili $item['categoryId']
):
{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
<ul>
{foreach $categoryItems as $item}
<li>{$item->name}</li>
{/foreach}
</ul>
{/foreach}
Filter lahko uporabimo tudi kot funkcijo v Latte, kar nam omogoča alternativno sintakso:
{foreach group($items, categoryId) ...}
.
Če želite elemente razvrstiti v skupine glede na bolj zapletena merila, lahko v parametru filter uporabite funkcijo. Če bi na primer elemente grupirali glede na dolžino njihovega imena, bi bilo to videti takole:
{foreach ($items|group: fn($item) => strlen($item->name)) as $items}
...
{/foreach}
Pomembno je opozoriti, da $categoryItems
ni navadno polje, temveč objekt, ki se obnaša kot iterator. Za dostop
do prvega elementa v skupini lahko uporabite first()
funkcijo.
Zaradi te prilagodljivosti pri grupiranju podatkov je group
izjemno uporabno orodje za predstavitev podatkov
v predlogah Latte.
Vgnezdene zanke
Recimo, da imamo tabelo v zbirki podatkov z drugim stolpcem subcategoryId
, ki opredeljuje podkategorije za vsak
element. Vsako glavno kategorijo želimo prikazati v ločenem <ul>
seznamu, vsako podkategorijo pa v ločeni
ugnezdeni zanki. <ol>
seznamu:
{foreach ($items|group: categoryId) as $categoryItems}
<ul>
{foreach ($categoryItems|group: subcategoryId) as $subcategoryItems}
<ol>
{foreach $subcategoryItems as $item}
<li>{$item->name}
{/foreach}
</ol>
{/foreach}
</ul>
{/foreach}
Povezava s podatkovno bazo Nette
Pokažimo, kako učinkovito uporabiti združevanje podatkov v kombinaciji s podatkovno bazo Nette. Predpostavimo, da delamo
s tabelo items
iz začetnega primera, ki je prek stolpca categoryId
povezana s to tabelo
categories
:
categoryId | name |
---|---|
1 | Sadje |
2 | Jeziki |
3 | Barve |
Podatke iz preglednice items
naložimo z ukazom raziskovalca podatkov Nette Database Explorer
$items = $db->table('items')
. Med iteracijo nad temi podatki imamo možnost ne le dostopa do atributov, kot sta
$item->name
in $item->categoryId
, temveč zaradi povezave s tabelo categories
tudi
do povezane vrstice v njej prek $item->category
. Ta povezava lahko pokaže zanimive načine uporabe:
{foreach ($items|group: category) as $category => $categoryItems}
<h1>{$category->name}</h1>
<ul>
{foreach $categoryItems as $item}
<li>{$item->name}</li>
{/foreach}
</ul>
{/foreach}
V tem primeru uporabimo filter |group
za združevanje po povezani vrstici $item->category
, ne le
po stolpcu categoryId
. Tako dobimo ActiveRow
dane kategorije v spremenljivki ključ, kar nam omogoča
neposreden prikaz njenega imena z uporabo {$category->name}
. To je praktični primer, kako lahko združevanje
v skupine poenostavi predloge in olajša obdelavo podatkov.
Filter |batch
Filter omogoča razdelitev seznama elementov v skupine z vnaprej določenim številom elementov. Ta filter je idealen v primerih, ko želite podatke predstaviti v več manjših skupinah, na primer zaradi boljše preglednosti ali vizualne organizacije na strani.
Predstavljajte si, da imamo seznam elementov in jih želimo prikazati v seznamih, od katerih vsak vsebuje največ tri
elemente. Uporaba filtra |batch
je v takem primeru zelo praktična:
<ul>
{foreach ($items|batch: 3) as $batch}
{foreach $batch as $item}
<li>{$item->name}</li>
{/foreach}
{/foreach}
</ul>
V tem primeru je seznam $items
razdeljen na manjše skupine, pri čemer vsaka skupina ($batch
)
vsebuje največ tri elemente. Vsaka skupina se nato prikaže v ločenem <ul>
seznamu.
Če zadnja skupina ne vsebuje dovolj elementov, da bi dosegli želeno število, lahko z drugim parametrom filtra določite, s čim bo ta skupina dopolnjena. To je idealno za estetsko poravnavo elementov, kjer bi nepopolna vrstica lahko bila videti neurejena.
{foreach ($items|batch: 3, '—') as $batch}
...
{/foreach}
Oznaka {iterateWhile}
Ista opravila, ki smo jih obravnavali s filtrom |group
, bomo prikazali z uporabo oznake
{iterateWhile}
. Glavna razlika med pristopoma je, da group
najprej obdela in združi vse vhodne podatke,
medtem ko {iterateWhile}
nadzoruje potek ciklov s pogoji, zato iteracija poteka zaporedno.
Najprej narišemo tabelo s kategorijami z uporabo iterateWhile:
{foreach $items as $item}
<ul>
{iterateWhile}
<li>{$item->name}</li>
{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
</ul>
{/foreach}
Medtem ko {foreach}
označuje zunanji del cikla, tj. risanje seznamov za vsako kategorijo, oznaka
{iterateWhile}
označuje notranji del, tj. posamezne elemente. Pogoj v končni oznaki pove, da se bo ponavljanje
nadaljevalo, dokler trenutni in naslednji element pripadata isti kategoriji ($iterator->nextValue
je naslednji element).
Če bi bil pogoj vedno izpolnjen, bi bili v notranjem ciklu narisani vsi elementi:
{foreach $items as $item}
<ul>
{iterateWhile}
<li>{$item->name}
{/iterateWhile true}
</ul>
{/foreach}
Rezultat bo videti takole:
<ul>
<li>Apple</li>
<li>Banana</li>
<li>PHP</li>
<li>Green</li>
<li>Red</li>
<li>Blue</li>
</ul>
Kako se na ta način uporablja iterateWhile? Ko je tabela prazna in ne vsebuje elementov, ni praznih
<ul></ul>
se izpiše.
Če pogoj določimo v začetni oznaki {iterateWhile}
, se obnašanje spremeni: pogoj (in prehod na naslednji
element) se izvede na začetku notranjega cikla in ne na koncu. Tako, medtem ko vedno vnesemo {iterateWhile}
brez
pogojev, vnesemo {iterateWhile $cond}
šele, ko je izpolnjen pogoj $cond
. Hkrati se naslednji element
zapiše v $item
.
To je uporabno na primer v primeru, ko želimo prvi element v vsaki kategoriji prikazati drugače, na primer takole:
<h1>Apple</h1>
<ul>
<li>Banana</li>
</ul>
<h1>PHP</h1>
<ul>
</ul>
<h1>Green</h1>
<ul>
<li>Red</li>
<li>Blue</li>
</ul>
Prvotno kodo spremenimo tako, da najprej prikažemo prvi element, nato pa v notranjem ciklu {iterateWhile}
prikažemo druge elemente iz iste kategorije:
{foreach $items as $item}
<h1>{$item->name}</h1>
<ul>
{iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
<li>{$item->name}</li>
{/iterateWhile}
</ul>
{/foreach}
Znotraj enega cikla lahko ustvarimo več notranjih zank in jih celo ugnezdimo. Na ta način lahko na primer združimo podkategorije.
Recimo, da ima tabela še en stolpec subcategoryId
, in poleg tega, da je vsaka kategorija v ločenem
<ul>
, vsaka podkategorija v ločenem ciklu <ol>
:
{foreach $items as $item}
<ul>
{iterateWhile}
<ol>
{iterateWhile}
<li>{$item->name}
{/iterateWhile $item->subcategoryId === $iterator->nextValue->subcategoryId}
</ol>
{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
</ul>
{/foreach}