如何使用PHP和SQL创建“多维树菜单”?
我搜索了一会儿,但在谷歌和其他论坛上找不到任何东西。但这很奇怪,因为这是我们大学里很受欢迎的任务。所以我认为这篇文章也可以帮助其他人解决同样的问题 我有一个任务: 创建多维树菜单深度未定义,可以是4或7,取决于用户的意愿,应该有添加新元素、编辑、删除和显示整个树结构等选项。使用PHP、SQL和最小CSS 树的可视示例:如何使用PHP和SQL创建“多维树菜单”?,php,html,css,sql,Php,Html,Css,Sql,我搜索了一会儿,但在谷歌和其他论坛上找不到任何东西。但这很奇怪,因为这是我们大学里很受欢迎的任务。所以我认为这篇文章也可以帮助其他人解决同样的问题 我有一个任务: 创建多维树菜单深度未定义,可以是4或7,取决于用户的意愿,应该有添加新元素、编辑、删除和显示整个树结构等选项。使用PHP、SQL和最小CSS 树的可视示例: +Menu +Shop +Tshirts +Yellow +Green +Pants
+Menu
+Shop
+Tshirts
+Yellow
+Green
+Pants
+Forum
+Ideas
正如你所看到的,它有4个深度等级:菜单->商店->T恤->黄色
但我必须这样做,用户可以添加任意多的级别和元素
有什么例子吗?我应该使用什么样的SQL结构?
谢谢大家! 我建议MySQL采用以下结构: I_ID唯一、自动递增、项目名称、项目父ID、子项 子项可能包含该特定项的每个“子项”的I_ID的base64编码、序列化PHP数组 root元素的父ID为root或-1或其他,因此要从数据库中检索该ID,您首先要选择父ID为root或-1或其他任何选项。这是武断的 然后,使用PHP对子数组进行解码,并从系统中选择每个ID 重复上述步骤,直到不再有孩子。递归函数在这里可以很好地为您服务
当您将每一行添加到DOM中时,给它们一个特定的类,使它们隐藏起来。单击+时,使用javascript将该元素的所有子元素更改为具有一个不隐藏的类,并将刚刚单击的+按钮替换为-按钮。类似地处理减号按钮。解决方案非常简单: SQL结构 表格菜单项int id、varchar title、varchar link、int level、bool是父项 您可以添加附加链接、颜色等选项 默认级别为1。 默认值为_parent=false 之后,继续将条目输入数据库。如果项有子项-is_parent=true,并且所有子项都有父项级别的+1级 在输出中,只需添加任何新级别项目缩进的格式。 另外,如果项目的链接是页面的当前URL,则突出显示该项目为活动
仅此而已。您希望使用ID和parentID保存数据库中的每个元素,如果不存在这样的父元素,则该ID和parentID可以为null。PHP是您最大的问题,但在这里,引用是您将平面结构转换为树结构的好朋友 考虑以下DB结果:
----------------------------
| id | parentID | text |
|----|----------|----------|
| 1 | null | Item #1 |
| 2 | 5 | Item #2 |
| 3 | 2 | Item #3 |
| 4 | 2 | Item #4 |
| 5 | null | Item #5 |
| 6 | 5 | Item #6 |
| 7 | 3 | Item #7 |
| 8 | 5 | Item #8 |
| 9 | 1 | Item #9 |
| 10 | 7 | Item #10 |
----------------------------
考虑以下可能来自DB结果的数组-尽管ID是键很重要。您可以简单地将DB结果转换为以下内容—唯一需要的键是parentID:
$menu = array(
1 => array('text' => 'Item #1', 'parentID' => null),
2 => array('text' => 'Item #2', 'parentID' => 5),
3 => array('text' => 'Item #3', 'parentID' => 2),
4 => array('text' => 'Item #4', 'parentID' => 2),
5 => array('text' => 'Item #5', 'parentID' => null),
6 => array('text' => 'Item #6', 'parentID' => 5),
7 => array('text' => 'Item #7', 'parentID' => 3),
8 => array('text' => 'Item #8', 'parentID' => 5),
9 => array('text' => 'Item #9', 'parentID' => 1),
10 => array('text' => 'Item #10', 'parentID' => 7),
);
并将其转化为树状结构:
<?php
$addedAsChildren = array();
foreach ($menu as $id => &$menuItem) { // note that we use a reference so we don't duplicate the array
if (!empty($menuItem['parentID'])) {
$addedAsChildren[] = $id; // it should be removed from root, but we'll do that later
if (!isset($menu[$menuItem['parentID']]['children'])) {
$menu[$menuItem['parentID']]['children'] = array($id => &$menuItem); // & means we use the REFERENCE
} else {
$menu[$menuItem['parentID']]['children'][$id] = &$menuItem; // & means we use the REFERENCE
}
}
unset($menuItem['parentID']); // we don't need parentID any more
}
unset($menuItem); // unset the reference
foreach ($addedAsChildren as $itemID) {
unset($menu[$itemID]); // remove it from root so it's only in the ['children'] subarray
}
导致:
<ul><li>Item #1<ul><li>Item #9</li></ul></li><li>Item #5<ul><li>Item #2<ul><li>Item #3<ul><li>Item #7<ul><li>Item #10</li></ul></li></ul></li><li>Item #4</li></ul></li><li>Item #6</li><li>Item #8</li></ul></li></ul>
…并呈现:
下面是我的链接目录脚本的类别表中的代码,它完成了您要查找的内容: 数据库设计:
CREATE TABLE IF NOT EXISTS `categories` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(36) COLLATE utf8_unicode_ci NOT NULL,
`parent` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
)
要使用PHP在破折号中打印它们,请执行以下操作:
function parse($tree,$parent = 0,$level = 0){
$level++;
foreach ($tree as $p) {
if ($p['parent'] != $parent) continue;
$p['name'] = str_repeat('-',$level-1) . $p['name'];
echo "<option name='cat' value='{$p['id']}'>{$p['name']}</option>";
parse ($tree, $p['id'],$level);
}
}
$q = $link->query("SELECT * FROM `categories` ORDER BY name ASC");
$cats = array();
while($row = $q->fetch()){
$cats[] = array("id"=>$row['id'],"name"=>$row['name'],"parent"=>$row['parent'],"level"=>0);
}
parse($cats)
如果使用$level参数而不是破折号作为输出,则可以删除该参数。请看这篇文章:那么我的数据库中需要多少表来完成此操作?它如何知道哪个是父母,哪个是孩子?你能在代码中加些注释吗?我有点困惑。谢谢大家!@Ignas只有一个表,每个菜单项有一行。id是项的id,parentID是父菜单项的id。IKt正在工作,但它如何知道谁是谁的孩子?你能解释一下这行吗:$meniu[$meniuItem['parentID']]['children']-你从哪里得到的['children']?@Ignas$menu[$menuItem['parentID']]将是父$menuItem如果parentID是5,这等于$menu[5]。这里我们首先检查它是否有儿童密钥?如果没有,我们将创建它,但是如果它已经有一个子键,那么我们只需将项添加到该数组中。哦,我明白了,稍后在我们决定谁是父项之后,我们将取消设置它,对吗?
function parse($tree,$parent = 0,$level = 0){
$level++;
foreach ($tree as $p) {
if ($p['parent'] != $parent) continue;
$p['name'] = str_repeat('-',$level-1) . $p['name'];
echo "<option name='cat' value='{$p['id']}'>{$p['name']}</option>";
parse ($tree, $p['id'],$level);
}
}
$q = $link->query("SELECT * FROM `categories` ORDER BY name ASC");
$cats = array();
while($row = $q->fetch()){
$cats[] = array("id"=>$row['id'],"name"=>$row['name'],"parent"=>$row['parent'],"level"=>0);
}
parse($cats)