使用嵌套的无序列表构建树

时间:2012-01-07 06:24:12

标签: php mysql tree hierarchy

如何构建此HTML代码:

<ul class="tree">
    <li>Animals
        <ul>
            <li>Birds</li>
            <li>Mammals
                <ul>
                    <li>Elephant</li>
                    <li>Mouse</li>
                </ul>
            </li>
            <li>Reptiles</li>
        </ul>
    </li>
    <li>Plants
        <ul>
            <li>Flowers
                <ul>
                    <li>Rose</li>
                    <li>Tulip</li>
                </ul>
            </li>
            <li>Trees</li>
        </ul>
    </li>
</ul>

从这个结构:

CREATE TABLE `categories` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `position` INT(11) DEFAULT NULL,
  `parent_id` INT(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `parent_id_fk` (`parent_id`),
  CONSTRAINT `categories_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `categories` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `categories` (`id`, `position`, `parent_id`)
VALUES
    (1,1,NULL),
    (2,2,NULL),
    (3,1,1),
    (4,2,1),
    (5,1,4),
    (6,2,4),
    (7,3,1),
    (8,1,2),
    (9,1,8),
    (10,2,8),
    (11,2,2);

CREATE TABLE `categories_locale` (
  `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `slug` VARCHAR(100) NOT NULL DEFAULT '',
  `name` VARCHAR(40) NOT NULL DEFAULT '',
  `path_cache` text,
  `category_id` INT(11) NOT NULL,
  `locale_id` SMALLINT(5) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `categories_locale` (`id`, `slug`, `name`, `path_cache`, `category_id`, `locale_id`)
VALUES
    (1,'animals','Animals',NULL,1,1),
    (2,'plants','Plants',NULL,2,1),
    (3,'birds','Birds',NULL,3,1),
    (4,'mammals','Mammals',NULL,4,1),
    (5,'elephant','Elephant',NULL,5,1),
    (6,'mouse','Mouse',NULL,6,1),
    (7,'reptiles','Reptiles',NULL,7,1),
    (8,'flowers','Flowers',NULL,8,1),
    (9,'rose','Rose',NULL,9,1),
    (10,'tulip','Tulip',NULL,10,1),
    (11,'trees','Trees',NULL,11,1);

3 个答案:

答案 0 :(得分:2)

嗯,我相信必须有一些关于如何实现这一目标的在线例子。他们中的一些人甚至可能会谈论存储分层数据的新方法,你会发现读数很有趣。

无论如何,这段基于递归的代码片段可能会帮助您实现HTML。

<?php
// recursive function to generate the category HTML
function generateTree ($parent) {
    global $arrPCat, $arrCat;
    if (array_key_exists($parent, $arrPCat)) {
        echo '<ul' . ($parent == 0 ? ' class="tree"' : '') . '>';
        foreach ($arrPCat[$parent] as $arrC) {
            echo '<li>' . $arrC['name'] . '</li>';
            generateTree($arrC['id']);
        }
        echo '</ul>';
    }
}

// read all categories from the DB
$rs = mysql_query('SELECT  `cl`.`id`, `cl`.`name`, `c`.`position`, IFNULL(`c`.`parent_id`, 0) AS `parent_id`
    FROM  `categories_locale`  `cl`
    LEFT JOIN  `categories`  `c` ON  `cl`.`id` =  `c`.`id`
    ORDER BY  `c`.`parent_id` ,  `c`.`position`');
while ($r = mysql_fetch_assoc($rs)) {
    // store parent and its children into the $arrPCat Array
    $arrPCat[$r['parent_id']][] = Array (
                                    'id' => $r['id'],
                                    'name' => $r['name']
                                  );
}
generateTree (0); // now generate the HTML for the category tree
?>

希望它有所帮助!

答案 1 :(得分:0)

尝试在PHP中构建实际树,然后使用深度优先搜索来生成HTML。

答案 2 :(得分:0)

Abhay回答我遇到了一个小错误。他的解决方案并没有使UL嵌套在LI中,至少在我实现他的解决方案时。但是,它快速修复。在递归调用之后,您只需要回显关闭的li标记。这允许每个列表项在结束之前完全创建,即使它没有任何子项。

Abhay的代码:

foreach ($arrPCat[$parent] as $arrC) {
        echo '<li>' . $arrC['name'] . '</li>';
        generateTree($arrC['id']);
    }

更正:

foreach ($arrPCat[$parent] as $arrC) {
        echo '<li>' . $arrC['name'] ;
        generateTree($arrC['id']);
        echo '</li>';
    }