您希望使用 ID 和 parentID 保存数据库中的每个元素(如果不存在这样的父 ID,则可以为 null)。 PHP 是您“最大”的问题,但参考是您将平面结构转变为树形结构的好朋友。
考虑以下数据库结果:
----------------------------
| 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 是键很重要。您可以简单地将数据库结果转换为以下内容(唯一需要的键是“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 的方式输出它:
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>
..并渲染:
DEMO