Verschachtelte sql abfrage bzw. sortierung?
So, ich habe ein Problem.
Gerne möchte ich daten als liste aus einer datenbank laden. diese daten sollen seiten anzeigen als tabelle, diese seiten haben aber teilweise untergeordnete seiten die in der datenbank unter 'parent' die 'id' des elternelementes und diese wiederum können auch untergeordnete seiten haben.
wie gestalte ich die datenbankabfrage wenn ich die seiten anzeigen will in einer tabelle in der erst die "Höchste" nach dem 'sort' wert absteigend und zwischen diesem sort und dem nächsten "höchsten" datensatz dazwischen die unterseiten erscheinen?
hier ein bild der Tabelle:
anhin ein codeschnipsel der tabelle die ich schon habe:
<?php if (!empty($pages)): ?>
<table>
<thead>
<tr>
<th>ID</th>
<th>Link</th>
<th>Titel</th>
<th>Navigationselement</th>
<th>Aktionen</th>
</tr>
</thead>
<tbody>
<?php foreach($pages AS $page): ?>
<tr>
<td><?php echo e($page->id); ?></td>
<td><?php echo e($page->slug); ?></td>
<td><?php echo e($page->title); ?></td>
<td><?php echo e($page->nav); ?></td>
<td>
<form method="POST" action="./?route=admin/page/delete">
<input type="hidden" name="csrf_token" value="<?php echo csrf_token(); ?>" />
<input type="hidden" name="id" value="<?php echo e($page->id); ?>" />
<input type="submit" value="Löschen" class="button-as-link" />
</form>
<a href="./?route=admin/page/edit&id=<?php echo e($page->id); ?>">Editieren</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php else: ?>
<p>Es wurden noch keine Seiten angelegt.</p>
<?php endif; ?>
1 Antwort
Da es sich hierbei um eine hierarchische Struktur handelt, würde ich die Daten mit PHP in einen Tree einlesen, in dem die Subknoten entsprechend der sort-Spalte sortiert werden.
Sehr einfach gehaltene Beispielimplementation für einen Tree:
class TreeNode {
public $title, $children, $order;
public function __construct($title, $order) {
$this->children = array();
$this->title = $title;
$this->order = $order;
}
public function add($title, $order) {
$newNode = new TreeNode($title, $order);
$this->children[] = $newNode;
usort($this->children, fn($a, $b) => $a->order > $b->order);
return $newNode;
}
}
Sobald alle Daten aus der Datenbank ausgelesen und als Knoten im Tree eingeordnet wurden, kann über den Tree traversiert werden.
Beispiel:
function traverse($node) {
if (!is_null($node->title)) {
echo $node->title;
}
foreach ($node->children as $child) {
traverse($child);
}
}
$root = new TreeNode(null, 0);
// insert data entries as sub nodes ...
traverse($root);
In deinem Fall wäre die Reihenfolge der Ausgabe folgendermaßen:
Home
Bereiche
Yoga
Massagen
Angebot
Energyhealing
Ja, die Datensätze aus der Datenbank musst du auf jeden Fall erst auslesen. Ausgehend von deinem derzeitigen Resultat, müssten die einzelnen Array-Einträge nun noch in eine Baumstruktur überführt werden:
------------- root ----------
| |
Home ------------ Bereiche -----
| | |
Yoga Massagen Energyhealing
|
Angebot
Das macht die spätere Ausgabe einfacher.
Auf meiner obigen Beispielimplementation des Trees kannst du aufbauen. Zum Füllen brauchst du lediglich einen leeren Knoten (als Wurzelknoten) anlegen, mit der add-Funktion werden ihm Subknoten angefügt.
Die Implementation müsste von dir allerdings noch etwas angepasst/erweitert werden.
- Jeder Knoten muss seine ID kennen, denn anhand dieser wird ermittelt, wo ein Knoten im Baum angehängt werden muss.
- Du brauchst eine Suchfunktion, die rekursiv über den Wurzelknoten ($this) traversiert und einen Knoten mit einer bestimmten ID findet oder bei Nichtfund null zurückliefert.
- Beim Hinzufügen eines Knotens muss geprüft werden, ob sein Elternknoten existiert. Wenn ja, kann der neue Knoten als Kindknoten eingehängt werden. Andernfalls müsste ein Elternknoten kreiert werden, der temporär erst einmal nur seine ID kennt und unter den Rootknoten gehängt wird.
- Beim Hinzufügen eines Knotens muss zuerst geprüft werden, ob er bereits existiert. Wenn ja, handelt es sich um einen der temporär angelegten Elternknoten. Er muss also noch um Titel, Reihennummer und Eltern-ID ergänzt werden. Des Weiteren muss eine Verschiebung im Baum stattfinden (Knoten aus children-Array des Wurzelknotens entfernen, korrektes Elternelement finden und dem den Knoten als Kind zuordnen.
Kannst du mir das näher erleutern?
also zuerst alle daten auslesen?
ich rufe die daten aus der datenbank in ein Model, hier die ausgabe: