Php无限层级并显示层级数
时间:2019-06-13
本文章向大家介绍Php无限层级并显示层级数,主要包括Php无限层级并显示层级数使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
今天在处理递归无限层级菜单时,遇到一个稍微烧脑的问题,如何显示当前节点所在的层级数。
废话不多说,我们先看个直观的无限层级:
<?php // 这里的arr是直接从数据库取出的,仅作为测试数据 $arr = array( array('id' => 1, 'name' => '一级菜单a', 'pid' => 0),// pid 父级id array('id' => 2, 'name' => '一级菜单b', 'pid' => 0), array('id' => 3, 'name' => '二级菜单a', 'pid' => 1), array('id' => 4, 'name' => '二级菜单b', 'pid' => 1), array('id' => 5, 'name' => '二级菜单c', 'pid' => 2), array('id' => 6, 'name' => '二级菜单d', 'pid' => 2), array('id' => 7, 'name' => '三级菜单a', 'pid' => 3), array('id' => 8, 'name' => '三级菜单b', 'pid' => 3), array('id' => 9, 'name' => '四级菜单a', 'pid' => 8), ); /** 获取所有子节点 * @param $data 所有节点数组 * @param $id $pid 父级节点id * @param $level 层级 * @return array */ function getTree($data, $pid, $level = 0) { $list = array(); foreach ($data as $k => $v) { if ($v['pid'] == $pid) { $v['level'] = $level; $v['name'] = $v['name'].'('.($level+1).'级)'; // 这里可以加个层级次数 $v['children'] = getTree($data, $v['id'], $level + 1); if ($v['children'] == null){ unset($v['children']); } $list[] = $v; } } return $list; } $menu = getTree($arr, 0, 0); $json = json_encode($menu); ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="https://cdn.jsdelivr.net/npm/vue"></script> <style> *{ box-sizing: border-box; margin: 0;padding: 0; } *:before,*:after{ box-sizing: border-box; } ul, li { list-style: none; } .l_tree_container { width: 100%; height: 100%; box-shadow: 0 0 3px #ccc; margin: 13px; position: relative; } .l_tree { width: calc(100% - 44px); height: 100%; padding-left: 42px; } .l_tree_branch { width: 100%; height: 100%; display: block; padding: 13px; position: relative; } .l_tree_branch .l_tree_children_btn { width: 19px; height: 19px; background-color: #23b1f0; font-size: 14px; text-align: center; color: #ffffff; outline: none; border: 0; cursor: pointer; } ul.l_tree:before { content: ''; border-left: 1px dashed #999999; height: calc(100%); position: absolute; left: 10px; top: 0px; } .l_tree .l_tree_branch:last-child::before { content: ''; width: 3px; height: calc(100% - 24px); display: block; background-color: #ffffff; position: absolute; bottom: 0; left: -34px; } .l_tree, .l_tree_branch { position: relative; } .l_tree_branch::after { content: ''; width: 40px; height: 0; border-bottom: 1px dashed #000; position: absolute; right: calc(100% - 9px); top: 22px; } .l_tree_container>.l_tree::before, .l_tree_container>.l_tree>.l_tree_branch::after { display: none; } </style> </head> <body> <div id="demo"> <div class="l_tree_container"> <ew-tree :model="testdata"></ew-tree> </div> </div> <script> // 树组件 Vue.component('ew-tree', { template: ` <ul class="l_tree"> <li class="l_tree_branch" v-for="item in model" :key="item.id"> <div class="l_tree_click"> <button type="button" class="l_tree_children_btn" v-if="item.children" @click="toggle(item)">{{ !item.show ? '-' : '+' }}</button> <span class="l_folder">{{ item.name }}</span> </div> <ew-tree v-show="!item.show" v-if="item.children" :model="item.children"></ew-tree> </li> </ul>`, props: { model: {} }, methods: { toggle: function (item) { var idx = this.model.indexOf(item) Vue.set(this.model[idx], 'show', !item.show) } } }); new Vue({ el: "#demo", data() { return { testdata: <?php echo $json?> } } }) </script> </body> </html>
我们看到所有节点层级数没问题,那么我如何查看节点中pid=3的所有节点层级关系呢
$menu = getTree($arr, 3, 0);
显然不对,况且菜单展示并不友好,pid=3的父节点至少要显示在顶层吧。层级数暂且不管,我们先解决如何显示顶层pid=3的树形结构:
pid=3对应的节点是:二级菜单a。这个可以直接根据数据id查询出来,此处仅做演示哈。调整下代码:
$menu = getTree($arr, 3, 0); $menu = array(['name' => '二级菜单a','children'=> $menu]); $json = json_encode($menu);
OK,完美,同样要显示所有pid=1的节点层级关系,一样,pid=1对应的节点是 一级菜单a
$menu = getTree($arr, 1, 0); $menu = array(['name' => '一级菜单a','children'=> $menu]); $json = json_encode($menu);
好,回到 刚才的话题,如何正确的显示每个节点所在的层级数呢? 这里我也思考了很久,也没找到快捷的方法。
最终我还是递归的查询本节点所有的父节点id集合:完整代码如下:
<?php // 这里的arr是直接从数据库取出的,仅作为测试数据 $arr = array( array('id' => 1, 'name' => '一级菜单a', 'pid' => 0),// pid 父级id array('id' => 2, 'name' => '一级菜单b', 'pid' => 0), array('id' => 3, 'name' => '二级菜单a', 'pid' => 1), array('id' => 4, 'name' => '二级菜单b', 'pid' => 1), array('id' => 5, 'name' => '二级菜单c', 'pid' => 2), array('id' => 6, 'name' => '二级菜单d', 'pid' => 2), array('id' => 7, 'name' => '三级菜单a', 'pid' => 3), array('id' => 8, 'name' => '三级菜单b', 'pid' => 3), array('id' => 9, 'name' => '四级菜单a', 'pid' => 8), ); /** 获取所有子节点 * @param $data 所有节点数组 * @param $id $pid 父级节点id * @param $level 层级 * @return array */ function getTree($data, $pid, $level = 0) { $list = array(); foreach ($data as $k => $v) { if ($v['pid'] == $pid) { $v['level'] = $level; $v['name'] = $v['name'] . '(' . ($level + 1) . '级)'; // 这里可以加个层级次数 $v['children'] = getTree($data, $v['id'], $level + 1); if ($v['children'] == null) { unset($v['children']); } $list[] = $v; } } return $list; } /** 根据子节点获取父节点id * @param $data 所有节点数组 * @param $id id 主键id * @return array */ function getParentid($data, $id) { $arr = array(); foreach ($data as $v) { if ($v['id'] == $id) { $arr[] = $v; //$arr[$v['id']]=$v['name']; $arr = array_merge(getParentid($data, $v['pid']), $arr); } } return $arr; } $id = 8 ; // 对应的节点是: 三级菜单b 对应的pid 是 3 $pid = 3; // 对应的节点是 二级菜单a $toparr = getParentid($arr, $id); // 节点为8的所有父节点 id: 1 3 8 这里包含了自身,注意剔除 $level = count($toparr); // 节点所在的层级数 $menu = getTree($arr, $pid, $level-1); if($pid) $menu = array(['name' => '二级菜单a' . '(' . ($level-1) . '级)', 'children' => $menu]); $json = json_encode($menu); ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="https://cdn.jsdelivr.net/npm/vue"></script> <style> * { box-sizing: border-box; margin: 0; padding: 0; } *:before, *:after { box-sizing: border-box; } ul, li { list-style: none; } .l_tree_container { width: 100%; height: 100%; box-shadow: 0 0 3px #ccc; margin: 13px; position: relative; } .l_tree { width: calc(100% - 44px); height: 100%; padding-left: 42px; } .l_tree_branch { width: 100%; height: 100%; display: block; padding: 13px; position: relative; } .l_tree_branch .l_tree_children_btn { width: 19px; height: 19px; background-color: #23b1f0; font-size: 14px; text-align: center; color: #ffffff; outline: none; border: 0; cursor: pointer; } ul.l_tree:before { content: ''; border-left: 1px dashed #999999; height: calc(100%); position: absolute; left: 10px; top: 0px; } .l_tree .l_tree_branch:last-child::before { content: ''; width: 3px; height: calc(100% - 24px); display: block; background-color: #ffffff; position: absolute; bottom: 0; left: -34px; } .l_tree, .l_tree_branch { position: relative; } .l_tree_branch::after { content: ''; width: 40px; height: 0; border-bottom: 1px dashed #000; position: absolute; right: calc(100% - 9px); top: 22px; } .l_tree_container > .l_tree::before, .l_tree_container > .l_tree > .l_tree_branch::after { display: none; } </style> </head> <body> <div id="demo"> <div class="l_tree_container"> <ew-tree :model="testdata"></ew-tree> </div> </div> <script> // 树组件 Vue.component('ew-tree', { template: ` <ul class="l_tree"> <li class="l_tree_branch" v-for="item in model" :key="item.id"> <div class="l_tree_click"> <button type="button" class="l_tree_children_btn" v-if="item.children" @click="toggle(item)">{{ !item.show ? '-' : '+' }}</button> <span class="l_folder">{{ item.name }}</span> </div> <ew-tree v-show="!item.show" v-if="item.children" :model="item.children"></ew-tree> </li> </ul>`, props: { model: {} }, methods: { toggle: function (item) { var idx = this.model.indexOf(item) Vue.set(this.model[idx], 'show', !item.show) } } }); new Vue({ el: "#demo", data() { return { testdata: <?php echo $json?> } } }) </script> </body> </html>
同样要显示所有节点:直接把pid赋值0,比如:
$id = 2 ; // 对应的节点是: 一级菜单b 对应的pid 是 0 $pid = 0; // 对应的节点是 0 为 一级节点 显示所有节点,上面的$id用不到 $toparr = getParentid($arr, $id); // $level = count($toparr); // 节点所在的层级数 $menu = getTree($arr, $pid, $level-1); if($pid) $menu = array(['name' => '二级菜单a' . '(' . ($level-1) . '级)', 'children' => $menu]); $json = json_encode($menu);
看起来没毛病,博友们如果有好的办法获取任意一个节点所处的层级数,欢迎拍砖留言哈。
原文地址:https://www.cnblogs.com/applelife/p/11016616.html
- CentOS挂载硬盘
- 使用jQuery UI的draggable和droppable完成拖拽功能--介绍
- Angular企业级开发(6)-使用Gulp构建和打包前端项目
- CSS魔法堂:重拾Border之——解构Border
- Angular企业级开发(7)-MVC之控制器
- Angular企业级开发(8)-控制器的作用域
- 使用jQuery Draggable和Droppable实现拖拽功能
- CSS魔法堂:重拾Border之——图片作边框
- Mobile Web中URL设计问题
- 使用root用户连接Ubuntu16.04时,提示SSH连接被拒绝
- CSS魔法堂:Box-Shadow没那么简单啦:)
- java操作redis: 将string、list、map、自定义的对象保存到redis中
- 运行第一个Docker容器-Docker for Web Developers(1)
- 手动实现jQuery Tools里面tab功能
- php概述
- php教程
- php环境搭建
- PHP书写格式
- php变量
- php常量
- PHP注释
- php数组
- php字符串 string
- PHP整型 integer
- PHP浮点型 float
- php布尔型
- php数据类型之数组
- php数据类型之对象
- php数据类型之null
- php数据类型之间的转换
- php运算符
- php表达式
- PHP循环控制
- PHP流程控制
- php函数
- php全局变量
- PHP魔术变量
- php命名空间
- php 日期
- PHP包含文件
- php文件
- PHP 文件上传
- php Cookies
- php Sessions
- php email
- php安全email
- php错误处理
- PHP异常处理
- php过滤器
- PHP 高级过滤器
- php json
- php 表单
- PHP MySQL 简介
- PHP 连接 MySQL
- php创建数据库
- php 创建表
- php mysq 插入数据
- PHP MySQL 插入多条数据
- PHP MySQL 预处理语句
- php mysql 读取数据
- php mysql where
- PHP MySQL Order By
- PHP MySQL Update
- PHP MySQL Delete
- php ODBC
- mybatis文件映射之利用延迟加载解决collection分布查询(六)
- 【C++】攻克哈希表(unordered_map)
- 位图原理及实现 - 海量数据处理标配
- mybatis文件映射之利分布查询时传递多列值 (七)
- 位运算 - 初见
- Mybatis学习笔记(一)
- mybatis文件映射之鉴别器discriminator标签
- LeetCode刷题总结 -- 链表篇
- LeetCode刷题总结 -- 数组篇
- 剑指offer(07-09)题解
- 学以致用C++设计模式 之 “适配器模式”
- FTP文件管理项目(本地云)项目日报(九)
- 【Linux】血泪教训 -- 动态链接库配置方法
- FTP文件管理项目(本地云)项目日报(八)
- FTP文件管理项目(本地云)项目日报(七)