我知道一篇关于如何正确执行此操作并在 mysql 中具有良好性能的完美文章(我不能相信这个想法,我只是从捷克语翻译它)。
你需要这样的树结构:
categories (
id,
lft, -- index on "left iteration" - number on the left
rgt, -- index on "right iteration" - number on the right
depth,
)
如何显示完整的树:
$result = mysql_query("SELECT * FROM categories ORDER BY lft");
while ($row = mysql_fetch_assoc($result)) {
echo str_repeat("- ", $row["depth"]) . htmlspecialchars($row["data"]) . "<br />";
}
mysql_free_result($result);
如果您需要打印一整棵树,只需将其排序lft
并写下来即可。如果您只需要显示树的一部分,您可以限制两者lft
并且rft
确实大于当前节点值。
显示在有序列表中:
$result = mysql_query("SELECT * FROM categories ORDER BY lft");
$depth = -1;
while ($row = mysql_fetch_assoc($result)) {
if ($depth < $row["depth"]) {
echo "<ul>";
} else {
echo str_repeat("</li></ul>", $depth - $row["depth"]) . "</li>";
}
echo "<li>\n" . htmlspecialchars($row["data"]);
$depth = $row["depth"];
}
echo str_repeat("</li></ul>", $depth + 1) . "\n";
mysql_free_result($result);
在有序列表(具有多个级别)中显示时,您必须检测当前节点depth
和下一个项目之间的连接。
将其用于“面包屑导航”:
$row = mysql_fetch_assoc(mysql_query("SELECT * FROM categories WHERE id = " . intval($_GET["id"])));
$result1 = mysql_query("SELECT * FROM categories WHERE lft < $row[lft] AND rgt > $row[rgt] ORDER BY lft");
while ($row1 = mysql_fetch_assoc($result1)) {
echo "<a href='?id=$row1[id]'>" . htmlspecialchars($row1["data"]) . "</a> > ";
}
mysql_free_result($result1);
echo htmlspecialchars($row["data"]);
将孩子添加到列表的末尾:
mysql_query("INSERT INTO categories (lft, rgt, depth, data)
SELECT IFNULL(MAX(rgt), 0) + 1, IFNULL(MAX(rgt), 0) + 2, 0, '" .
mysql_real_escape_string($_POST["data"]) . "' FROM categories");
将子节点添加到您需要的任何位置
mysql_query("START TRANSACTION");
$row = mysql_fetch_assoc(mysql_query("SELECT * FROM categories WHERE id = " . intval($_GET["rodic"]) . " FOR UPDATE"));
mysql_query("UPDATE categories SET lft = lft + 2 WHERE lft > $row[rgt]");
mysql_query("UPDATE categories SET rgt = rgt + 2 WHERE rgt >= $row[rgt]");
mysql_query("INSERT INTO categories (lft, rgt, depth, data) VALUES ($row[rgt], $row[rgt]+1, $row[depth]+1, '" . mysql_real_escape_string($_POST["data"]) . "')");
mysql_query("COMMIT");
删除完整的孩子
mysql_query("START TRANSACTION");
$row = mysql_fetch_assoc(mysql_query("SELECT * FROM categories WHERE id = " . intval($_GET["id"]) . " FOR UPDATE"));
mysql_query("DELETE FROM categories WHERE lft >= $row[lft] AND rgt <= $row[rgt]");
$rozdil = $row["rgt"] - $row["lft"] + 1;
mysql_query("UPDATE categories SET lft = lft - $rozdil WHERE lft > $row[rgt]");
mysql_query("UPDATE categories SET rgt = rgt - $rozdil WHERE rgt > $row[rgt]");
mysql_query("COMMIT");
如果您知道此算法的更多信息(或名称),请告诉我
我建议使用 PDO 编写此内容。