来自:mjsws > 馆藏分类
配色: 字号:
PHP实现无限极分类的两种方式
2018-12-15 | 阅:  转:  |  分享 
  
PHP实现无限极分类的两种方式,递归和引用面试的时候被问到无限极分类的设计和实现,比较常见的做法是在建表的时候,增加一个PID字段用来区别自
己所属的分类$array=array(array(''id''=>1,''pid''=>0,''name''=>''河北省''
),array(''id''=>2,''pid''=>0,''name''=>''北京市''),array(''id''=>3,
''pid''=>1,''name''=>''邯郸市''),array(''id''=>4,''pid''=>2,''name''
=>''朝阳区''),array(''id''=>5,''pid''=>2,''name''=>''通州区''),array(''id
''=>6,''pid''=>4,''name''=>''望京''),array(''id''=>7,''pid''=>4,
''name''=>''酒仙桥''),array(''id''=>8,''pid''=>3,''name''=>''永年区''),ar
ray(''id''=>9,''pid''=>1,''name''=>''武安市''),);1234567891011数据在数据库
中存储大概是这个样子,怎么实现无限极递归呢,有两种常用的做法,递归和引用算法递归算法/递归实现无限极分类@par
am$array分类数据@param$pid父ID@param$level分类级别@return$
list分好类的数组直接遍历即可$level可以用来遍历缩进/functiongetTree($array,$pi
d=0,$level=0){//声明静态数组,避免递归调用时,多次声明导致数组覆盖static$list=[];
foreach($arrayas$key=>$value){//第一次遍历,找到父节点为根节点的节点也就是pid=
0的节点if($value[''pid'']==$pid){//父节点为根节点的节点,级别为0,也就是第一级$value[
''level'']=$level;//把数组放到list中$list[]=$value;//把这个节点从数组中移除,减
少后续递归消耗unset($array[$key]);//开始递归,查找父ID为该节点ID的节点,级别则为原级别+1getT
ree($array,$value[''id''],$level+1);}}return$list;}/获得递
归完的数据,遍历生成分类/$array=getTree($array);foreach($array)as$val
ue{echostr_repeat(''--'',$value[''level'']),$value[''name''].''
>'';}//输出结果无限极分类实现ok河北省--邯郸市----永年区--武安市北京市--朝阳区----望京----酒仙桥--通
州区123456789101112131415161718192021222324252627282930313233343536
373839404142434445464748引用算法functiongenerateTree($array){//第一步
构造数据$items=array();foreach($arrayas$value){$items[$value[''
id'']]=$value;}//第二部遍历数据生成树状结构$tree=array();foreach($ite
msas$key=>$value){if(isset($items[$item[''pid'']])){$items[$i
tem[''pid'']][''son''][]=&$items[$key];}else{$tree[]=&$items[$k
ey];}}return$tree;}//经过第一步数据变成了这样乐淘棋牌http://www.letaoqpyx.co
mArray([1]=>Array([id]=>1[pid]=>0[name]=>河北省[childr
en]=>Array())[2]=>Array([id]=>2[pid]=>0[name]=>
北京市[children]=>Array())[3]=>Array([id]=>3[pid]=>1
[name]=>邯郸市[children]=>Array())[4]=>Array([id]=>4
[pid]=>2[name]=>朝阳区[children]=>Array())[5]=>Array
([id]=>5[pid]=>2[name]=>通州区[children]=>Array())[6
]=>Array([id]=>6[pid]=>4[name]=>望京[children]=>Arra
y())[7]=>Array([id]=>7[pid]=>4[name]=>酒仙桥[childr
en]=>Array())[8]=>Array([id]=>8[pid]=>3[name]=>
永年区[children]=>Array())[9]=>Array([id]=>9[pid]=>1
[name]=>武安市[children]=>Array()))//第一步很容易就能看懂,就是构造数据,现在咱们
仔细说一下第二步$tree=array();//遍历构造的数据foreach($itemsas$key=>$va
lue){//如果pid这个节点存在if(isset($items[$value[''pid'']])){//把当前的$valu
e放到pid节点的son中注意这里传递的是引用为什么呢?$items[$value[''pid'']][''son''][]=
&$items[$key];}else{$tree[]=&$items[$key];}}//这个方法的核心在于引用,p
hp变量默认的传值方式是按指传递//也就是说假如说遍历顺序是河北省邯郸市当遍历到河北省时会把河北省放到tree中遍历
到邯郸市时会把邯郸市放到河北省的子节点数组中但是!!!这会儿的tree数组中河北省已经放进去了根据php变量按值传递的规
则你并没有更改tree数组中的河北省的数据所以这里用到了引用传递//当你对河北省做更改时,tree数组中的河北省也一并做了更改
下面我们做个实验我们把引用传递去掉,看一下结果移动电玩城http://www.44226.net//使用普通传值输出结果Ar
ray([0]=>Array([id]=>1[pid]=>0[name]=>河北省)[1]=>A
rray([id]=>2[pid]=>0[name]=>北京市))//可以看到只有河北省和北京市输出出来了
因为他们俩是第一级节点而且排行1和2,放到$tree数组中之后,没有使用引用传递,那么后续对他俩的子节点的操作都没有在$tre
e中生效,现在我们更改一下顺序把邯郸市放到河北省的前面那么根据咱们的推断那么邯郸市就应该出现在tree数组里//邯郸市放到河
北省前面的输出结果Array([0]=>Array([id]=>1[pid]=>0[name]=>河北省
[son]=>Array([0]=>Array([id]=>3[pid]=>1[name]=>邯
郸市)))[1]=>Array([id]=>2[pid]=>0[name]=>北京市))//果然
是这样那么证明我们的推断是正确的现在我们把引用传值改回去再看一下//使用引用传值输出结果Array([1]=>Arra
y([id]=>1[pid]=>0[name]=>河北省[children]=>Array([0]
=>Array([id]=>3[pid]=>1[name]=>邯郸市[children]=>Array
([0]=>Array([id]=>8[pid]=>3[name]=>永年区)))[1]=>
Array([id]=>9[pid]=>1[name]=>武安市)))[2]=>Array(
[id]=>2[pid]=>0[name]=>北京市[children]=>Array([0]=>A
rray([id]=>4[pid]=>2[name]=>朝阳区[children]=>Array([0]=>Array([id]=>6[pid]=>4[name]=>望京)[1]=>Array([id]=>7[pid]=>4[name]=>酒仙桥)))[1]=>Array([id]=>5[pid]=>2[name]=>通州区))))//树状结构完美的输出出来了这个方法的核心就是引用传值
献花(0)
+1
(本文系mjsws首藏)