如何创建"多维树菜单"使用PHP和SQL?

时间:2014-04-11 08:00:47

标签: php html css sql

我搜索了一段时间,但在谷歌和其他论坛上找不到任何东西。但它很奇怪,因为它是我们大学的热门任务。所以我认为这篇文章也可能对其他问题有所帮助。

我有一个任务:

“创建多维树状菜单(深度未定义,可能是4或7,具体取决于用户的意愿),应该有添加新元素,编辑,删除和显示整个树结构的选项。使用PHP,SQL和最小化CSS“。

树的可视示例:

+Menu
    +Shop
        +Tshirts
            +Yellow
            +Green
        +Pants
    +Forum
        +Ideas

正如您所看到的那样,它有4个深度级别:Menu->Shop->tshirt->yellow 但我必须做到这一点,以便用户可以添加他想要的级别和元素。

是否有任何示例以及我应该继续使用哪种SQL结构? 谢谢!

4 个答案:

答案 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>

..并呈现:

enter image description here enter image description here

DEMO

答案 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)

如果使用

  • 而不是破折号输出,则可以删除$ level参数。