本期概要:
使用递归实现无限级菜单分类
一、数据结构 一般情况下,我们的数据表常规设计如下:
| id | name | pid |
| 1 | PHP 技术 | 0 |
| 2 | Linux 技术 | 0 |
| 3 | PHP 基础 | 1 |
| 4 | PHP 高级 | 1 |
| 5 | PHP 数据类型 | 3 |
| 6 | PHP 数据类型 - 字符串 | 5 |
| 7 | Linux 基础 | 2 |
| 8 | Linux 简单命令 | 7 |
当我们从数据库中查询出数据,得到二维数组结构如下:
[ [ "id": 1, "name": "PHP 技术", "pid": 0 ],
[ "id": 3, "name": "PHP 基础", "pid": 1 ],
[ "id": 5, "name": "PHP 数据类型", "pid": 3 ],
[ "id": 6, "name": "PHP 数据类型 - 字符串", "pid": 5 ],
[ "id": 4, "name": "PHP 高级", "pid": 1 ],
[ "id": 2, "name": "Linux 技术", "pid": 0 ],
[ "id": 7, "name": "Linux 基础", "pid": 2 ],
[ "id": 8, "name": "Linux 简单命令", "pid": 7 ]
]
我们要实现无限级菜单,主要核心思路就是:
找出每个菜单所在的层级(level)
那么我们就需要用到递归,得出每个菜单对应的层级
function _infinite($_data, $_pid = 0, $_level = 0) {
// 定义静态变量,防止每次都初始化
static $_new_data = [];
// 循环,得出每个数据对应的层级
foreach ($_data as $_key => $_value) {
// 第一次遍历,找到父节点为根节点的节点,即:pid = 0
if ($_value['pid'] == $_pid) {
// 当该节点为根节点时,对应的层级设为 0,即:level = 0
$_value['level'] = $_level;
// 把该节点放入数组中
$_new_data[] = $_value;
// 得出节点层级后,删除该节点,减少递归的消耗
unset($_data[$_key]);
// 开始递归,查找所有 pid 为当前节点 id 的数据,层级加 1,作为对应的子节点
_infinite($_data, $_value['id'], $_level + 1);
}
}
// 返回带层级的新数组
return $_new_data;
}
调用方法,我们可以得到新数组:
[ [ "id": 1, "name": "PHP 技术", "pid": 0, "level": 0 ],
[ "id": 3, "name": "PHP 基础", "pid": 1, "level": 1 ],
[ "id": 5, "name": "PHP 数据类型", "pid": 3, "level": 2 ],
[ "id": 6, "name": "PHP 数据类型 - 字符串", "pid": 5, "level": 3 ],
[ "id": 4, "name": "PHP 高级", "pid": 1, "level": 1 ],
[ "id": 2, "name": "Linux 技术", "pid": 0, "level": 0 ],
[ "id": 7, "name": "Linux 基础", "pid": 2, "level": 1 ],
[ "id": 8, "name": "Linux 简单命令", "pid": 7, "level": 2 ]
]
我们得到新数据以后,需要将数据根据需要的 view 展示出来,我这里使用树形结构打印:
function _show_tree($_data) {
$_html = '';
foreach ($_data as $_key => $_value) {
if ($_value['level'] > 0) {
$_prefix = '|' . str_repeat('--', $_value['level']);
} else {
$_prefix = '';
}
$_html .= $_prefix . '<a href="###">' . $_value['name'] . '</a><br />';
}
return $_html;
}
得到效果图如下:
这样我们就完成了使用递归实现无限级分类的效果。