Verschachtelte sql abfrage bzw. sortierung?

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
Thooms 
Fragesteller
 13.11.2023, 10:46

Kannst du mir das näher erleutern?

also zuerst alle daten auslesen?

hier die datenbankabfrage: 
    public function fetchAll(): array {
        $stmt = $this->pdo->prepare('SELECT * FROM `pages` ORDER BY `assort` ASC');
        $stmt->execute();
        return $stmt->fetchAll(PDO::FETCH_CLASS, PagesModel::class);
    }

ich rufe die daten aus der datenbank in ein Model, hier die ausgabe:

array(6) { [0]=> object(App\Pages\PagesModel)#17 (6) { ["id"]=> int(6) ["slug"]=> string(4) "home" ["title"]=> string(4) "Home" ["parent"]=> int(0) ["nav"]=> int(1) ["assort"]=> int(1) } [1]=> object(App\Pages\PagesModel)#18 (6) { ["id"]=> int(12) ["slug"]=> string(4) "yoga" ["title"]=> string(4) "Yoga" ["parent"]=> int(15) ["nav"]=> int(0) ["assort"]=> int(1) } [2]=> object(App\Pages\PagesModel)#19 (6) { ["id"]=> int(13) ["slug"]=> string(7) "massage" ["title"]=> string(8) "Massagen" ["parent"]=> int(15) ["nav"]=> int(0) ["assort"]=> int(2) } [3]=> object(App\Pages\PagesModel)#20 (6) { ["id"]=> int(14) ["slug"]=> string(7) "healing" ["title"]=> string(13) "Energyhealing" ["parent"]=> int(15) ["nav"]=> int(0) ["assort"]=> int(3) } [4]=> object(App\Pages\PagesModel)#21 (6) { ["id"]=> int(15) ["slug"]=> string(5) "areas" ["title"]=> string(8) "Bereiche" ["parent"]=> int(0) ["nav"]=> int(1) ["assort"]=> int(2) } [5]=> object(App\Pages\PagesModel)#22 (6) { ["id"]=> int(16) ["slug"]=> string(5) "offer" ["title"]=> string(7) "Angebot" ["parent"]=> int(13) ["nav"]=> int(0) ["assort"]=> int(1) } }
0
regex9  13.11.2023, 19:09
@Thooms

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.
0