首先咱们来看数据表php
从上图中能够发现,中国下有贵州,北京两个子节点,而北京有天安门一个子节点,纽约的子节点是“纽约的子类”。thinkphp
从pid为0看出,中国和纽约是顶级节点。数据库
由于贵州的pid是1,而中国的id为1,因此贵州的父节点是中国,至于type字段,能够不用管,只是我本身的项目须要。数组
能够发现,着写数据在数据表中是无序的,并无咱们想象中的层次结构分明而且可读性很好。app
那么,当使用无限极分类以后数据的输出是怎样的呢?以下:thinkphp5
这样就可以很清晰的看出他们的层次结构了,那么这样的效果在thinkphp5.0是怎么实现的呢?this
好了,贴出代码:url
<?php /** * Created by PhpStorm. * User: Administrator * Date: 2017/9/24 * Time: 17:14 */ namespace app\admin\model; use think\Model; class Cate extends Model { public function cateTree(){ $res=$this->select(); if($res){ $result=$this->sort($res); return $result; } } public function sort($data,$pid=0,$level=0){
//此处数据必须是静态数组,否则递归的时候每次都会声明一个新的数组 static $arr=array(); foreach ($data as $key=>$value){ if($value['pid'] == $pid){ $value["level"]=$level; $arr[]=$value; $this->sort($data,$value['id'],$level+1); } } return $arr; } }
首先咱们能够看到,在cateTree方法中咱们经过select()方法获取到了数据库里面的全部数据,而后将数据传入到sort里面,此刻咱们注意到sort有三个参数,pid表示当前节点的父节点的id,level表示当前节点spa
为几级。(顶级节点是0级,顶级节点的子节点是1级),那么level的用处到时候输出的时候会用到,此处不用纠结。3d
当数据传入sort方法以后,声明一个静态数组,保证每次递归调用的时候数组里面的数据不会改变,而后循环从数据库里面查询的数据。
$value的值表示数据库里面的一行,是一个数组,$value['名字']表示一行里面的一个字段。
首先咱们经过
$value['pid'] == $pid
判断当前的pid是否为0,由于咱们在sort方法一开始的时候就给了一个默认值0,此时$pid为0。
这样作的目的就是选出第一个顶级节点。
若是找到了第一个顶级节点,假如是中国,那么知足if的条件,就进入条件体,先给$value数组加一个level值,而后再把$value整个假如到静态数组当中去。
而后开始递归,注意,此刻sort方法的pid参数接受的是当前节点的id。为何要这样传呢?
举个例子:
若是咱们循环到了中国,以下图
第一次递归的时候,会将static 数组入栈,以及将变量入栈,并保存程序的断点,以便递归完成以后可以顺利的找到进入递归出并继续执行程序。
如上图,找到中国后,递归,入栈,此刻静态数组里面只有“中国”一个数据。(注意:数组是一个二维数组,我只是为了简便才画了一维数组,数组里面还包含了level的信息)。经过pid判断中国下方是否有子节点,而后匹配到贵州以后,进入递归,数据入栈。此时静态数组里面又增长了贵州这个数据。
到了贵州以后,发如今咱们的数据表里面并无贵州的子节点,此时递归结束,程序返回递纳入口处,继续执行循环体,栈空间以下:
当递归回来时,贵州出栈,此时栈空间里面保存的是中国的数据,包括pid为0这个变量,level为0这个变量,以及静态数组。当执行下一个循环时,$value['pid'] == $pid
由于栈空间里面保存的pid是0,因此会找到北京这个数据。
接下来的步骤就差很少了,首先foreach循环天安门的子节点,发现没有子节点,递归结束,同时将sort($data,7,3)出栈,回到递归进入出,以上为例,则回到天安门那段代码的sort处,同时执行foreach循环,查找是否有其余的节点的pid为6,即查看北京下是否还有其余子节点。若是有,则将该节点的数据入栈,若是没有则出栈,回到北京那块代码的sort处,匹配pid为1的是否还有其余节点。若是没有则回到最开始的sort处,此时递归彻底结束。
此刻咱们来观察数组,能够看出,经过递归,数组里的数据开始变得有序起来,如贵州是中国的一级子节点,因此紧跟在中国以后,当第一轮递归结束,到了第二轮递归时,第一个找到的是北京,因此数组里面第三个元素是北京。
那怎么获得以下的格式化数据呢?
咱们能够发现,北京和贵州的level是相同的,注意:咱们的数组还保存得有level信息(图中的level有些错误,不建议你们参考)。
level数值大的前面的短线就越多,表示级数就越大。
那么这是怎么输出的呢?
{volist name="cateList" id="cate"} <!--设置URL值,方便JS删除的时候获取路径--> <tr id="{:url('delete',array('id'=>$cate.id))}" class="url"> <td align="center">{$cate.id}</td> <td><?php echo str_repeat("-",$cate["level"]*8)?>{$cate.cate_name}</td> {/volist}
以上是thinkphp的模板标签,volist和foreach是同样的道理
经过后台分配而来的cateList数据(也就是上面的静态数组),经过
<td><?php echo str_repeat("-",$cate["level"]*8)?>{$cate.cate_name}</td>获得最终的结果。