Nette Documentation Preview

syntax
Vse, kar ste kdaj želeli vedeti o združevanju
*********************************************
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Vse, kar ste kdaj želeli vedeti o združevanju

Pri delu s podatki v predlogah lahko pogosto naletite na potrebo po njihovem združevanju ali specifičnem prikazu glede na določena merila. Latte za ta namen ponuja več močnih orodij.

Filter in funkcija |group omogočata učinkovito združevanje podatkov glede na določen kriterij, filter |batch pa olajša razdelitev podatkov v fiksne serije, značka {iterateWhile} pa omogoča bolj zapleteno upravljanje poteka zank s pogoji. Vsaka od teh značk ponuja specifične možnosti za delo s podatki, s čimer postanejo nepogrešljiva orodja za dinamičen in strukturiran prikaz informacij v predlogah Latte.

Filter in funkcija group

Predstavljajte si podatkovno tabelo items s postavkami, razdeljenimi v kategorije:

id categoryId name
1 1 Apple
2 1 Banana
3 2 PHP
4 3 Green
5 3 Red
6 3 Blue

Preprost seznam vseh postavk s pomočjo predloge Latte bi izgledal takole:

<ul>
{foreach $items as $item}
	<li>{$item->name}</li>
{/foreach}
</ul>

Če pa bi želeli, da so postavke urejene v skupine glede na kategorijo, jih moramo razdeliti tako, da bo vsaka kategorija imela svoj seznam. Rezultat bi moral izgledati 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 je mogoče enostavno in elegantno rešiti s pomočjo |group. Kot parameter navedemo categoryId, kar pomeni, da se postavke razdelijo v manjša polja glede na vrednost $item->categoryId (če bi bil $item polje, se uporabi $item['categoryId']):

{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
	<ul>
		{foreach $categoryItems as $item}
			<li>{$item->name}</li>
		{/foreach}
	</ul>
{/foreach}

Filter lahko v Latte uporabimo tudi kot funkcijo, kar nam daje alternativno sintakso: {foreach group($items, categoryId) ...}.

Če želite združevati postavke glede na bolj zapletena merila, lahko v parametru filtra uporabite funkcijo. Na primer, združevanje postavk glede na dolžino imena bi izgledalo takole:

{foreach ($items|group: fn($item) => strlen($item->name)) as $items}
	...
{/foreach}

Pomembno je vedeti, da $categoryItems ni običajno polje, ampak objekt, ki se obnaša kot iterator. Za dostop do prve postavke skupine lahko uporabite funkcijo first().

Ta fleksibilnost pri združevanju podatkov naredi group izjemno uporabno orodje za predstavitev podatkov v predlogah Latte.

Gnezdene zanke

Predstavljajmo si, da imamo podatkovno tabelo z dodatnim stolpcem subcategoryId, ki definira podkategorije posameznih postavk. Želimo prikazati vsako glavno kategorijo v ločenem seznamu <ul> in vsako podkategorijo v ločenem gnezdenem seznamu <ol>:

{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 z Nette Database

Poglejmo si, kako učinkovito izkoristiti združevanje podatkov v kombinaciji z Nette Database. Predpostavimo, da delamo s tabelo items iz uvodnega primera, ki je preko stolpca categoryId povezana s to tabelo categories:

categoryId name
1 Fruits
2 Languages
3 Colors

Podatke iz tabele items naložimo s pomočjo Nette Database Explorer ukaza $items = $db->table('items'). Med iteracijo nad temi podatki imamo možnost dostopati ne le do atributov kot sta $item->name in $item->categoryId, ampak zaradi povezave s tabelo categories tudi do povezane vrstice v njej preko $item->category. Na tej povezavi lahko demonstriramo zanimivo uporabo:

{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 uporabljamo filter |group za združevanje glede na povezano vrstico $item->category, ne le glede na stolpec categoryId. Zahvaljujoč temu imamo v spremenljivki ključa neposredno ActiveRow dane kategorije, kar nam omogoča neposredno izpisovanje njenega imena s pomočjo {$category->name}. To je praktičen primer, kako lahko združevanje naredi predloge bolj pregledne in olajša delo s podatki.

Filter |batch

Filter omogoča razdelitev seznama elementov v skupine s predhodno določenim številom elementov. Ta filter je idealen za situacije, ko želite podatke predstaviti v več manjših skupinah, na primer za boljšo preglednost ali vizualno ureditev na strani.

Predstavljajmo si, da imamo seznam postavk in jih želimo prikazati v seznamih, kjer vsak vsebuje največ tri postavke. 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 v manjše skupine, pri čemer vsaka skupina ($batch) vsebuje do tri postavke. Vsaka skupina je nato prikazana v ločenem <ul> seznamu.

Če zadnja skupina ne vsebuje dovolj elementov za dosego želenega števila, drugi parameter filtra omogoča definiranje, s čim bo ta skupina dopolnjena. To je idealno za estetsko poravnavo elementov tam, kjer bi nepopolna vrsta lahko delovala neurejeno.

{foreach ($items|batch: 3, '—') as $batch}
	...
{/foreach}

Značka {iterateWhile}

Enake naloge, kot smo jih reševali s filtrom |group, si bomo ogledali z uporabo značke {iterateWhile}. Glavna razlika med obema pristopoma je v tem, da group najprej obdela in združi vse vhodne podatke, medtem ko {iterateWhile} nadzoruje potek zank s pogoji, tako da iteracija poteka postopoma.

Najprej izrišemo tabelo s kategorijami s pomočjo 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 zanke, torej izrisovanje seznamov za vsako kategorijo, značka {iterateWhile} označuje notranji del, torej posamezne postavke. Pogoj v končni znački pravi, da se bo ponavljanje izvajalo, dokler trenutni in naslednji element pripadata isti kategoriji ($iterator->nextValue je naslednji element).

Če bi bil pogoj vedno izpolnjen, bi se v notranji zanki izrisali vsi elementi:

{foreach $items as $item}
	<ul>
		{iterateWhile}
			<li>{$item->name}
		{/iterateWhile true}
	</ul>
{/foreach}

Rezultat bo izgledal takole:

<ul>
	<li>Apple</li>
	<li>Banana</li>
	<li>PHP</li>
	<li>Green</li>
	<li>Red</li>
	<li>Blue</li>
</ul>

Za kaj je taka uporaba iterateWhile dobra? Ko bo tabela prazna in ne bo vsebovala nobenih elementov, se ne bo izpisalo prazno <ul></ul>.

Če navedemo pogoj v odpiralni znački {iterateWhile}, se vedenje spremeni: pogoj (in prehod na naslednji element) se izvede že na začetku notranje zanke, ne na koncu. Torej, medtem ko se v {iterateWhile} brez pogoja vedno vstopi, se v {iterateWhile $cond} vstopi le ob izpolnitvi pogoja $cond. In hkrati se s tem v $item zapiše naslednji element.

Kar pride prav na primer v situaciji, ko bomo želeli prvi element v vsaki kategoriji izrisati na drugačen način, 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 prilagodimo tako, da najprej izrišemo prvo postavko in nato v notranji zanki {iterateWhile} izrišemo nadaljnje postavke 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}

V okviru ene zanke lahko ustvarjamo več notranjih zank in jih celo gnezdnimo. Tako bi se dale združevati na primer podkategorije itd.

Recimo, da bo v tabeli še en stolpec subcategoryId in poleg tega, da bo vsaka kategorija v ločenem <ul>, bo vsaka podkategorija v ločenem <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}