Ich versuche, meine Daten, die hierarchisch mit einem Baumtraversalmodell aufgebaut sind, in ein
zu bekommen, um sie auf meiner Website anzuzeigen.
Hier ist mein Code:
function getCats($) {
// retrieve all children of $parent
$query = "SELECT max(rght) as max from t_categories";
$row = C_DB::fetchSingleRow($query);
$max = $row["max"];
$result ="<ul>";
$query = "SELECT * from t_categories where lft >=0 and rght <= $max";
if($rs = C_DB::fetchRecordset($query)){
$p_right ="";
$p_left ="";
$p_diff="";
while($row = C_DB::fetchRow($rs)){
$diff = $row["rght"] -$row["lft"];
if($diff == $p_diff){
$result.= "<li>".$row['title']."</li>";
}elseif (($row["rght"] - $row["lft"] > 1) && ($row["rght"] > $p_right)){
$result. "<ul>";
$result.= "<li>".$row['title']."</li>";
}else{
$result.= "<li>".$row['title']."</li>";
}
$p_right = $row["rght"];
$p_left = $row["lft"];
$p_diff = $diff;
}
}
$result.= "</ul>";
return $result;
}
Hier ist meine Beispieltabelle:
|ID | TITLE | lft| rght |
|1 | Cat 1 | 1 | 16 |
|18 | Cat 2 | 3 | 4 |
|22 | Cat 3 | 5 | 6 |
|28 | Cat 4 | 7 | 8 |
|34 | Cat 5 | 9 | 9 |
|46 | Cat 6 | 11 | 10 |
|47 | Cat 7 | 13 | 12 |
|49 | Cat 8 | 15 | 14 |
Jetzt gibt es etwas aus wie:
<ul>
<li>Cat 1</li>
<li>Cat 2</li>
<li>Cat 3</li>
<li>Cat 4</li>
<li>Cat 5</li>
<li>Cat 6</li>
<li>Cat 7</li>
<li>Cat 8</li>
</ul>
Kann mir jemand sagen, warum oder wie die Liste in einer hierarchischen Struktur ausgegeben wird?
Verwandtes Thema
Ok, machen wir ein bisschen Kopfgeldjagd 😉
Schritt 0 – Beispiel zur Desinfektion:
Wie bereits erwähnt, sind Ihre Beispieldaten fehlerhaft, da sie keine gültige verschachtelte Menge definieren. Wenn Sie diese Daten aus einer App übernommen haben, sollten Sie die Einfüge-/Löschlogik überprüfen.
Also habe ich zum Testen eine bereinigte Version wie folgt verwendet:
(MySQL hier, da es als erstes zur Hand war)
CREATE TABLE t_categories`(
`id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
`title` VARCHAR(45) NOT NULL,
`lft` INTEGER UNSIGNED NOT NULL,
`rght` INTEGER UNSIGNED NOT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 1',1,16);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 2',2,3);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 3',4,7);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 4',5,6);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 5',8,13);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 6',9,12);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 7',10,11);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 8',14,15);
Schritt 1 – Lassen Sie die Datenbank die Bestellung vornehmen
Verschachtelte Mengen wurden in erster Linie als bequeme Möglichkeit zum Speichern von Bäumen in Datenbanken erfunden, da sie es ziemlich einfach machen, nach Teilbäumen, übergeordneten Beziehungen und, in diesem Fall besonders interessant, nach Reihenfolge und Tiefe abzufragen:
SELECT node.title, (COUNT(parent.title) - 1) AS depth
FROM t_categories AS node
CROSS JOIN t_categories AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rght
GROUP BY node.title
ORDER BY node.lft
Dadurch wird Ihr Set ordentlich geordnet zurückgegeben, beginnend mit dem Stammknoten und bis zum Ende in Vorbestellung. Am wichtigsten ist, dass die Tiefe jedes Knotens als positive Ganzzahl hinzugefügt wird, die angibt, wie viele Ebenen sich der Knoten unter der Wurzel befindet (Ebene 0). Für die obigen Beispieldaten lautet das Ergebnis:
title, depth
'Cat 1', 0
'Cat 2', 1
'Cat 3', 1
'Cat 4', 2
'Cat 5', 1
'Cat 6', 2
'Cat 7', 3
'Cat 8', 1
In Code:
// Grab ordered data
$query = '';
$query .= 'SELECT node.title, (COUNT(parent.title) - 1) AS depth';
$query .= ' FROM t_categories AS node';
$query .= ' CROSS JOIN t_categories AS parent';
$query .= ' WHERE node.lft BETWEEN parent.lft AND parent.rght';
$query .= ' GROUP BY node.title';
$query .= ' ORDER BY node.lft';
$result = mysql_query($query);
// Build array
$tree = array();
while ($row = mysql_fetch_assoc($result)) {
$tree[] = $row;
}
Das resultierende Array sieht folgendermaßen aus:
Array
(
[0] => Array
(
Getting a modified preorder tree traversal model (nested set) into a
=> Cat 1
[depth] => 0
)
[1] => Array
(
Getting a modified preorder tree traversal model (nested set) into a
=> Cat 2
[depth] => 1
)
...
)
Schritt 2 – Ausgabe als HTML-Listenfragment:
While-Schleife verwenden:
// bootstrap loop
$result="";
$currDepth = -1; // -1 to get the outer <ul>
while (!empty($tree)) {
$currNode = array_shift($tree);
// Level down?
if ($currNode['depth'] > $currDepth) {
// Yes, open <ul>
$result .= '<ul>';
}
// Level up?
if ($currNode['depth'] < $currDepth) {
// Yes, close n open <ul>
$result .= str_repeat('</ul>', $currDepth - $currNode['depth']);
}
// Always add node
$result .= '<li>' . $currNode['title'] . '</li>';
// Adjust current depth
$currDepth = $currNode['depth'];
// Are we finished?
if (empty($tree)) {
// Yes, close n open <ul>
$result .= str_repeat('</ul>', $currDepth + 1);
}
}
print $result;
Gleiche Logik wie rekursive Funktion:
function renderTree($tree, $currDepth = -1) {
$currNode = array_shift($tree);
$result="";
// Going down?
if ($currNode['depth'] > $currDepth) {
// Yes, prepend <ul>
$result .= '<ul>';
}
// Going up?
if ($currNode['depth'] < $currDepth) {
// Yes, close n open <ul>
$result .= str_repeat('</ul>', $currDepth - $currNode['depth']);
}
// Always add the node
$result .= '<li>' . $currNode['title'] . '</li>';
// Anything left?
if (!empty($tree)) {
// Yes, recurse
$result .= renderTree($tree, $currNode['depth']);
}
else {
// No, close remaining <ul>
$result .= str_repeat('</ul>', $currNode['depth'] + 1);
}
return $result;
}
print renderTree($tree);
Beide geben die folgende Struktur aus:
<ul>
<li>Cat 1</li>
<li>
<ul>
<li>Cat 2</li>
<li>Cat 3</li>
<li>
<ul>
<li>Cat 4</li>
</ul>
</li>
<li>Cat 5</li>
<li>
<ul>
<li>Cat 6</li>
<li>
<ul>
<li>Cat 7</li>
</ul>
</li>
</ul>
</li>
<li>Cat 8</li>
</ul>
</li>
</ul>
Nitpickers-Ecke: Fragesteller ausdrücklich darum gebeten <ul>
aber bestellt ungeordnete Listen!? Komm schon…
😉
Sind Ihre Spalten benannt
links
undrechts
oderlft
undright
? Und spiegelt Ihr Code wider, was Sie tatsächlich haben?– Hobbs
21. August 09 um 8:21 Uhr
Entschuldigung, es wurde behoben. Ich musste meinen Code aus dem Niederländischen übersetzen 😉
– Schleifer
21. August 09 um 8:29 Uhr
out of topic: Aus vielen Gründen empfehle ich Ihnen, Ihren Code nur auf Englisch zu schreiben. Das ist eine gute Angewohnheit!
– Irukandji
21. August 09 um 8:49 Uhr
könntest du genau posten was die ausgabe ist sollen für diese Daten sein?
– Kipp
24. August 09 um 21:39 Uhr
Übrigens, das verschachtelte Set aus Ihrem Beispiel ist kaputt – Sie haben eine fehlende ‘2’ und die doppelte 9 auf Cat 5 macht genauso wenig Sinn wie die lft, die auf Cat 6 bis 8 größer als rechts ist …
– Henrik Opel
25. August 2009 um 20:23 Uhr