Was Sie schon immer über Gruppierung wissen wollten
Wenn Sie mit Daten in Vorlagen arbeiten, haben Sie oft das Bedürfnis, diese zu gruppieren oder sie nach bestimmten Kriterien anzuzeigen. Zu diesem Zweck bietet Latte mehrere leistungsstarke Werkzeuge.
Der Filter und die Funktion |group
ermöglichen eine effiziente Gruppierung von Daten nach bestimmten Kriterien,
während der Filter |batch
die Aufteilung von Daten in feste Chargen erleichtert und das Tag
{iterateWhile}
die Möglichkeit einer komplexeren Zyklussteuerung mit Bedingungen bietet. Jedes dieser Tags bietet
spezifische Optionen für die Arbeit mit Daten, was sie zu unverzichtbaren Werkzeugen für die dynamische und strukturierte
Anzeige von Informationen in Latte-Vorlagen macht.
Filter und Funktionen group
Stellen Sie sich eine Datenbanktabelle items
mit in Kategorien unterteilten Artikeln vor:
id | categoryId | name |
---|---|---|
1 | 1 | Apfel |
2 | 1 | Banane |
3 | 2 | PHP |
4 | 3 | Grün |
5 | 3 | Rot |
6 | 3 | Blau |
Eine einfache Liste aller Elemente mit einer Latte-Vorlage würde wie folgt aussehen:
<ul>
{foreach $items as $item}
<li>{$item->name}</li>
{/foreach}
</ul>
Wenn wir die Artikel jedoch nach Kategorien gruppieren wollen, müssen wir sie so unterteilen, dass jede Kategorie ihre eigene Liste hat. Das Ergebnis würde dann wie folgt aussehen:
<ul>
<li>Apple</li>
<li>Banana</li>
</ul>
<ul>
<li>PHP</li>
</ul>
<ul>
<li>Green</li>
<li>Red</li>
<li>Blue</li>
</ul>
Die Aufgabe kann einfach und elegant mit |group
gelöst werden. Wir geben categoryId
als Parameter
an, was bedeutet, dass die Elemente auf der Grundlage des Werts $item->categoryId
in kleinere Arrays aufgeteilt
werden (wenn $item
ein Array wäre, würden wir $item['categoryId']
):
{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
<ul>
{foreach $categoryItems as $item}
<li>{$item->name}</li>
{/foreach}
</ul>
{/foreach}
Der Filter kann auch als Funktion in Latte verwendet werden, wodurch wir eine alternative Syntax erhalten:
{foreach group($items, categoryId) ...}
.
Wenn Sie Elemente nach komplexeren Kriterien gruppieren möchten, können Sie eine Funktion im Filterparameter verwenden. Eine Gruppierung nach der Länge des Namens würde zum Beispiel so aussehen:
{foreach ($items|group: fn($item) => strlen($item->name)) as $items}
...
{/foreach}
Es ist wichtig zu beachten, dass $categoryItems
kein normales Array ist, sondern ein Objekt, das sich wie ein
Iterator verhält. Um auf das erste Element in der Gruppe zuzugreifen, können Sie die first()
Funktion verwenden.
Diese Flexibilität bei der Datengruppierung macht group
zu einem äußerst nützlichen Werkzeug für die
Darstellung von Daten in Latte-Vorlagen.
Verschachtelte Schleifen
Nehmen wir an, wir haben eine Datenbanktabelle mit einer weiteren Spalte subcategoryId
, die Unterkategorien für
jeden Artikel definiert. Wir möchten jede Hauptkategorie in einer separaten <ul>
Liste und jede Unterkategorie
in einer separaten geschachtelten <ol>
Liste anzeigen:
{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}
Verbindung mit der Nette-Datenbank
Lassen Sie uns zeigen, wie Sie die Datengruppierung in Kombination mit Nette Database effektiv nutzen können. Nehmen wir an,
wir arbeiten mit der Tabelle items
aus dem ersten Beispiel, die über die Spalte categoryId
mit dieser
Tabelle categories
verbunden ist:
categoryId | name |
---|---|
1 | Früchte |
2 | Sprachen |
3 | Farben |
Wir laden die Daten aus der Tabelle items
mit dem Nette Database Explorer Befehl
$items = $db->table('items')
. Bei der Iteration über diese Daten haben wir die Möglichkeit, nicht nur auf
Attribute wie $item->name
und $item->categoryId
zuzugreifen, sondern dank der Verbindung mit der
Tabelle categories
auch auf die zugehörige Zeile in dieser Tabelle über $item->category
. Diese
Verbindung kann interessante Anwendungen aufweisen:
{foreach ($items|group: category) as $category => $categoryItems}
<h1>{$category->name}</h1>
<ul>
{foreach $categoryItems as $item}
<li>{$item->name}</li>
{/foreach}
</ul>
{/foreach}
In diesem Fall verwenden wir den Filter |group
, um nach der verbundenen Zeile $item->category
zu
gruppieren, nicht nur nach der Spalte categoryId
. Dadurch erhalten wir die ActiveRow
der gegebenen
Kategorie im variablen Schlüssel, so dass wir ihren Namen mit {$category->name}
direkt anzeigen können. Dies ist
ein praktisches Beispiel dafür, wie die Gruppierung die Vorlagen vereinfachen und die Datenverarbeitung erleichtern kann.
Filter |batch
Mit dem Filter können Sie eine Liste von Elementen in Gruppen mit einer bestimmten Anzahl von Elementen aufteilen. Dieser Filter ist ideal für Situationen, in denen Sie Daten in mehreren kleineren Gruppen darstellen möchten, z. B. für eine bessere Übersichtlichkeit oder visuelle Organisation auf der Seite.
Stellen Sie sich vor, Sie haben eine Liste von Elementen und möchten diese in Listen darstellen, die jeweils maximal drei
Elemente enthalten. Die Verwendung des Filters |batch
ist in einem solchen Fall sehr praktisch:
<ul>
{foreach ($items|batch: 3) as $batch}
{foreach $batch as $item}
<li>{$item->name}</li>
{/foreach}
{/foreach}
</ul>
In diesem Beispiel wird die Liste $items
in kleinere Gruppen unterteilt, wobei jede Gruppe ($batch
)
bis zu drei Einträge enthält. Jede Gruppe wird dann in einer eigenen <ul>
Liste angezeigt.
Wenn die letzte Gruppe nicht genügend Elemente enthält, um die gewünschte Anzahl zu erreichen, können Sie mit dem zweiten Parameter des Filters festlegen, womit diese Gruppe ergänzt werden soll. Dies ist ideal, um Elemente ästhetisch auszurichten, bei denen eine unvollständige Reihe unordentlich aussehen könnte.
{foreach ($items|batch: 3, '—') as $batch}
...
{/foreach}
Tag {iterateWhile}
Wir werden die gleichen Aufgaben, die wir mit dem |group
Filter behandelt haben, mit dem
{iterateWhile}
Tag demonstrieren. Der Hauptunterschied zwischen den beiden Ansätzen besteht darin, dass
group
zunächst alle Eingabedaten verarbeitet und gruppiert, während {iterateWhile}
den Fortschritt von
Zyklen mit Bedingungen steuert, so dass die Iteration sequentiell erfolgt.
Zunächst wird mit iterateWhile eine Tabelle mit Kategorien gezeichnet:
{foreach $items as $item}
<ul>
{iterateWhile}
<li>{$item->name}</li>
{/iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
</ul>
{/foreach}
Während {foreach}
den äußeren Teil des Zyklus markiert, d. h. das Zeichnen von Listen für jede Kategorie,
markiert das Tag {iterateWhile}
den inneren Teil, d. h. die einzelnen Elemente. Die Bedingung im End-Tag besagt, dass
die Wiederholung so lange fortgesetzt wird, wie das aktuelle und das nächste Element zur selben Kategorie gehören
($iterator->nextValue
ist das nächste Element).
Wenn die Bedingung immer erfüllt wäre, würden alle Elemente im inneren Zyklus gezeichnet werden:
{foreach $items as $item}
<ul>
{iterateWhile}
<li>{$item->name}
{/iterateWhile true}
</ul>
{/foreach}
Das Ergebnis sieht dann so aus:
<ul>
<li>Apple</li>
<li>Banana</li>
<li>PHP</li>
<li>Green</li>
<li>Red</li>
<li>Blue</li>
</ul>
Wozu dient iterateWhile auf diese Weise? Wenn die Tabelle leer ist und keine Elemente enthält, wird kein leeres
<ul></ul>
gedruckt.
Wenn wir die Bedingung im einleitenden {iterateWhile}
-Tag angeben, ändert sich das Verhalten: Die Bedingung (und
der Übergang zum nächsten Element) wird am Anfang des inneren Zyklus ausgeführt, nicht am Ende. Während Sie also
{iterateWhile}
immer ohne Bedingungen eingeben, geben Sie {iterateWhile $cond}
nur ein, wenn die
Bedingung $cond
erfüllt ist. Und gleichzeitig wird das nächste Element in $item
geschrieben.
Dies ist z. B. dann nützlich, wenn wir das erste Element in jeder Kategorie anders darstellen wollen, etwa so:
<h1>Apple</h1>
<ul>
<li>Banana</li>
</ul>
<h1>PHP</h1>
<ul>
</ul>
<h1>Green</h1>
<ul>
<li>Red</li>
<li>Blue</li>
</ul>
Wir ändern den ursprünglichen Code so, dass wir zuerst das erste Element darstellen und dann im inneren Zyklus
{iterateWhile}
die anderen Elemente derselben Kategorie darstellen:
{foreach $items as $item}
<h1>{$item->name}</h1>
<ul>
{iterateWhile $item->categoryId === $iterator->nextValue->categoryId}
<li>{$item->name}</li>
{/iterateWhile}
</ul>
{/foreach}
Innerhalb eines Zyklus können wir mehrere innere Schleifen erstellen und diese sogar verschachteln. Auf diese Weise können zum Beispiel Unterkategorien gruppiert werden.
Angenommen, die Tabelle hat eine weitere Spalte subcategoryId
, und neben jeder Kategorie in einer separaten
<ul>
, jede Unterkategorie in einer separaten <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}