本期概要:
使用递归实现无限级菜单分类
复制代码
一、数据结构 一般情况下,我们的数据表常规设计如下:
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 . '' . $_value['name'] . '
';
}
return $_html;
}
复制代码
得到效果图如下:
这样我们就完成了使用递归实现无限级分类的效果。