转自:https://blog.csdn.net/belen_xue/article/details/59121554php
在各类栏目以及分类设置中,无限分类常常会被用到,而无限分类在进行排序的时候必然要用到递归,这里进行一次详细的分析解读。mysql
首先咱们先了解一下递归函数:sql
递归函数在语言学习的时候会单独拿出来学习,由于它很是经常使用,本质上来说递归函数就是调用本身的函数。数组
举个例子:函数
<?php function test(){ static $a=0; if($a<10){ $a++; test(); } echo $a."<br/>"; } test();
test函数里面又再调用了自身,这就是俗称的递归函数!递归函数都有条件设置,否则的会无限循环下去,这样会致使程序奔溃。学习
因此通常来说我总结递归函数有两个特色:fetch
一个是记录条件值,记录的条件值必须保证不会再下一次调用时丢失。spa
test函数里$a即是记录条件值,它是依靠使用static关键字来保证记录每次增长的数值不会再下一次调用test()函数而丢失,由于函数中static修饰的变量仅仅在第一次初始化,并保留变量值。因此只要保证这一点,不光static,其余的方式也能够达到目的,例如global还有&修饰符。.net
另外一个是条件检查。test里面对$a大小的限制就是该条件的检查过程。code
test函数中if($a<10)就是这个条件检查的过程,它限制了test()函数对自身的调用,这样就能够防止无限调用致使程序奔溃。
函数a内部调用另外的函数b,若是b函数没有完成,那么a函数就会一直等待下去,直到b函数完成,才会回到a函数继续执行。递归的过程当中利用了这个特性,正是这个能帮助咱们对无限分类进行排序,用上面test()递归函数说明:
上面test()打印出来的结果是:
10,10,10,10,10,10,10,10,10,10,10
可能和不少人想的不同,大概有许多人会以为不该该是0,1,2,3,4,5,6,7,8,9,10这样的结果吗?
这是由于函数test调用过程当中,只要$a<10,就会调用自身的test(),每次调用的test()都没有到达echo处,也就是每次调用的test函数并无完结,直到$a递增到了10,才第一次echo $a,这个时候$a已是10了,所以第一个10实际是递归了11次后的$a,第十一次递归的test因为不符合<10的条件该函数完结,这个时候才开始回到递归第十次test函数里执行echo,这个时候因为$a是静态变量,值已是10了,所以echo出的结果是10,下面依次回到以前的test函数完成前面未完成的echo步骤,所以echo出11个10,最后一个10实际是第一次执行test函数的echo结果。
无限分类的排序完成也是用的这个原理,递归排序函数不断的经过parentid等于上一级id的子类来匹配该类别的子类别,只要找到第一个子类,就用找到的这个子类的id去找下一级的子类,直到没有更下级的子类的时候,才返回上一级接着继续找,找到后又开始寻找该子类下一级子类,直到没有为止才返回,这个过程不断循环。可能用文字不太能理解,下面的实例中我会画出图例,请先日后看。
咱们先来看无限分类的数据er图:
例如一个裙子的类目,它有父类别女装,女装又属于衣服的类目,假定裙子的id为3,女装为2,衣服为1,那么裙子的parentid就是直接的上级类目裙子的id,所以parentid=2,而child是裙子所在的树形结构上所有的祖先元素id,那么child应该是1,2,3,所以裙子的深度deep为3,这里我假设的是用,隔开,也能够用其余的符号隔开,title不用说就是裙子。
具体咱们来看这个树形结构:
从树形结构分类还能够继续延伸下去,上一级的id是下一级的parentid,就是经过id和parent这两个列来实现基本的无限分类的,再进行无限分类的递归排序的时候也是依靠这两个字段的关系。
下面是一个无限分类的表结构以及数据的例子:
为了更清楚下面画了树形图:
上一代的类别的id就是自身的parentid,最高一级的parentid则为0,这点很是重要,是无限分类的排序的依据。
咱们所要的无限分类排序效果应该是各栏目下的子栏目都放到该栏目下方,用id进行排序,咱们要的效果就是下面这样,为了方便查看我用了tab以及|——来间隔区分栏目之间的关系:
衣服
|——男装
|——休闲上衣
|——短袖
|——长袖
|——休闲裤
|——女装
|——女装上衣
|——女装下装
|——牛仔裤
|——裙子
因为类别能够无限延伸下去,因此这里明显咱们须要使用递归函数进行排序分类。
获取数据全部结果,并按id排序
$mysqli=new mysqli('localhost','root','root','test')or die("链接失败"); $mysqli->set_charset("utf8"); $re=$mysqli->query("select * from col order by id asc"); $result=$re->fetch_all(MYSQLI_ASSOC);
递归排序函数
function recursion($result,$parentid=0){ /*记录排序后的类别数组*/ static $list=array(); foreach ($result as $k => $v){ if($v['parentid']==$parentid){ /*将该类别的数据放入list中*/ $list[]=$v; recursion($result,$v['id']); } } return $list; }
这个时候咱们就能获得按类别排序好的数组了,可是若是要有相应的格式,例如上面的|——,就须要对函数进行改进。
function recursion($result,$parentid=0,$format="|--"){ /*记录排序后的类别数组*/ static $list=array(); foreach ($result as $k => $v){ if($v['parentid']==$parentid){ if($parentid!=0){ $v['title']=$format.$v['title']; } /*将该类别的数据放入list中*/ $list[]=$v; recursion($result,$v['id']," ".$format); } } return $list; } $list=recursion($result,0,'|--');
这样排序的结果以下:
整个递归函数的执行状况大概是什么样的,咱们接上面说过的要画的实例图,看图后就很清楚这个原理了,这个图只画了部分,不过足够理解这个过程了: