我搜索了一段时间,但在谷歌和其他论坛上找不到任何东西。但它很奇怪,因为它是我们大学的热门任务。所以我认为这篇文章也可能对其他问题有所帮助。
我有一个任务:
“创建多维树状菜单(深度未定义,可能是4或7,具体取决于用户的意愿),应该有添加新元素,编辑,删除和显示整个树结构的选项。使用PHP,SQL和最小化CSS“。
树的可视示例:
+Menu
+Shop
+Tshirts
+Yellow
+Green
+Pants
+Forum
+Ideas
正如您所看到的那样,它有4个深度级别:Menu->Shop->tshirt->yellow
但我必须做到这一点,以便用户可以添加他想要的级别和元素。
是否有任何示例以及我应该继续使用哪种SQL结构? 谢谢!
答案 0 :(得分:6)
您希望使用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 |
----------------------------
考虑以下数组(可能来自数据库结果 - 但ID非常重要。您可以简单地将数据库结果转换为以下内容(唯一需要的键是& #34;的parentID&#34):
$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
的意义输出所有数据:
echo makeTree($menu);
function makeTree($menu) {
$tree = '<ul>';
foreach ($menu as $id => $menuItem) {
$tree .= '<li>' . $menuItem['text'];
if (!empty($menuItem['children'])) {
$tree .= makeTree($menuItem['children']);
}
$tree .= '</li>';
}
return $tree . '</ul>';
}
导致:
<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>
..并呈现:
答案 1 :(得分:0)
我建议使用MySQL的以下结构:
I_ID (unique, auto-increment), Item Name, Item Parent ID, Children
“Children”可能包含该特定项目的每个“子”的I_ID的base64编码的序列化PHP数组。
根元素的“父ID”为“root”或“-1”或者其他东西,所以要从数据库中检索这个,你首先要SELECT
任何有parent
的东西。 root或-1或者你选择的任何东西。这是任意的。
然后,使用PHP,您将解码children
数组,并从系统中选择每个ID。
重复直到没有更多的孩子。递归函数将为您提供良好的服务。
将每行添加到DOM中时,为它们指定一个隐藏它的特定类。单击“+”时,使用javascript更改该元素的所有子项以使其具有未隐藏的类,并使用“ - ”按钮替换刚刚单击的“+”按钮。同样处理减号按钮。
答案 2 :(得分:0)
解决方案非常简单:
SQL结构 table menu_entries(int id,varchar title,varchar link,int level,bool is_parent)
您可以添加其他链接,颜色等选项。
默认级别为1。 默认is_parent = false;
之后继续将您的条目输入数据库。如果item有子项 - is_parent = true,并且所有子项的级别都是父级别的+1级。
在输出中只添加格式化,任何新的“级别”项目都缩进。 此外,如果项目的链接是页面的当前URL,则将该项目突出显示为活动状态。
就是这样。
答案 3 :(得分:0)
来自我的链接目录脚本的类别表中的代码,它可以执行您正在寻找的内容:
数据库设计:
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)
如果使用