无限级菜单排序,怎么样写才最优雅?
原数据
$temp = [
['id' => 1, 'pid' => 0, 'name' => '商品管理'],
['id' => 2, 'pid' => 1, 'name' => '平台自营'],
['id' => 3, 'pid' => 2, 'name' => '图书品类'],
['id' => 4, 'pid' => 2, 'name' => '3C品类'],
['id' => 5, 'pid' => 0, 'name' => '第三方'],
['id' => 6, 'pid' => 5, 'name' => '家私用品'],
['id' => 7, 'pid' => 5, 'name' => '书法品赏'],
['id' => 8, 'pid' => 7, 'name' => '行书'],
['id' => 9, 'pid' => 8, 'name' => '行楷'],
['id' => 10, 'pid' => 9, 'name' => '张山行楷字帖'],
['id' => 11, 'pid' => 22, 'name' => '李四行楷字帖'],
];
pid 记录的是 父级 id,当为 0 时为第一级,现在对这段数据进行排序,让菜单层级排序,大家是怎么做的?
方案 1
思想:当拿到一个节点后,判断是否有该节点的子节点,如果有则为它的子菜单,子菜单递归前面的操作。
function te(array $arr, $node = 0)
{
$tem = [];
foreach ($arr as $val) {
$pid = $val['pid']; // 当前菜单的父级ID
$id = $val['id']; // 当前菜单ID
// 当前的父级ID和node节点匹配,说明当前子菜单属于node节点。
if ($pid == $node) {
$tem[$id] = $val; // 保存当前的菜单。
$son = te($arr, $id); // 递归 当前子菜单是否有子菜单?
// 当有的时候,保存 。
if (!empty($son)) {
$tem[$id]['son'] = $son;
}
}
}
return $tem;
}
function show(array $arr, $node = 0)
{
foreach ($arr as $val) {
if ($val['pid'] == 0) {
$node = 0;
}
for ($i = 0; $i < $node; $i++) {
echo '----';
}
echo $val['name'] . "\n";
if (isset($val['son'])) {
$node += 1;
show($val['son'], $node);
}
}
}
$menus = te($temp);
show($menus);
输出:
商品管理
----平台自营
--------图书品类
--------3C品类
第三方
----家私用品
----书法品赏
--------行书
------------行楷
----------------张山行楷字帖
方案 2
思想和方案1 一样,唯一不一样的地方是需要提前声明接收值。[该方法来之评论区。]
function traverseMenu(array $menus, array &$result, $pid = 0)
{
foreach ($menus as $child_menu) {
// 子菜单的 pid = $pid
// 说明它是 $pid 下面的子菜单
if ($child_menu['pid'] == $pid) {
// 包装为成我们需要的格式
$item = [
'id' => $child_menu['id'],
'name' => $child_menu['name'],
'children' => []
];
// 递归上面的操作,装完 所有 属于 $pid 下面的子菜单
traverseMenu($menus, $item['children'], $child_menu['id']);
// 至此完成 $pid 级下的所有子菜单装入 result 中
$result[] = $item;
}
}
}
测试代码
$result = [];
traverseMenu($temp, $result, 0);
print_r($result);
其它说明
- 本帖想通过 一个简短的、不超过
50
行的代码,让读者能够领悟其中精华,然后写出自己想要的东西。 - 发现有小伙伴直接贴一些 URL 链接,又不说明链接内容,让人费解,希望发言也有头有尾。
推荐文章: