PHP树结构,实现无限分级
一、从数据库查出来的数据需要id、parentid、level。
id唯一识别栏目,parentid为该栏目所属父类id,level标示该栏目是几级栏目。以下代码就可以实现一个简单的树结构。
1 public function tree2(){ 2 $r = array( 3 array( 4 'id'=>1, 5 'name'=>'智慧教育', 6 'parent_id'=>0, 7 'level'=>0 //一级分类 8 ), 9 array( 10 'id'=>2, 11 'name'=>'学校列表', 12 'parent_id'=>1, 13 'level'=>1 //二级分类 14 ), 15 array( 16 'id'=>4, 17 'name'=>'智慧医疗', 18 'parent_id'=>0, 19 'level'=>0 //一级分类 20 ), 21 array( 22 'id'=>5, 23 'name'=>'医院列表', 24 'parent_id'=>4, 25 'level'=>1 //二级分类 26 ), 27 array( 28 'id'=>6, 29 'name'=>'名医列表', 30 'parent_id'=>5, 31 'level'=>2 //三级分类 32 ) 33 34 ); 35 //输出为select标签: 36 echo '<h1>PHPTree</h1>'; 37 echo '<select style="width:300px;">'; 38 foreach($r as $item){ 39 echo '<option>'; 40 //根据所在的层次缩进 41 echo str_repeat('|—',$item['level']); 42 echo $item['name']; 43 echo '</option>'; 44 } 45 echo '</select>'; 46 }
页面效果图是这样的。
二、但是一般表结构中是没有level的。
这样就需要多层循环嵌套加if判断,先循环显示父级栏目parentid=0,及它就是一级栏目;然后再循环根据parentid与一级栏目的id判断,如果相等则显示对应的栏目,二级栏目就显示出来啦,以此类推,可以显示所有栏目。但这只适合已知栏目层数且层数不多的情况,因为要根据层数来判断遍历的次数。且如果层数过多,代码量就会很大。
1 public function tree3(){ 2 //从表中查到所有栏目 3 $cat = M('category'); 4 $allcat = $cat ->order('listorder ASC') ->select(); 5 6 //输出select标签 7 echo '<h2>栏目tree</h2>'; 8 echo '<select style="width:300px;">'; 9 foreach ($allcat as $val) { 10 if($val[parentid] == 0){ 11 echo '<option>'; 12 echo $val['catname']; 13 echo '</option>'; 14 } 15 foreach ($allcat as $value) { 16 if($val[id] == $value[parentid]){ 17 echo '<option>'; 18 echo '|—'.$value['catname']; 19 echo '</option>'; 20 } 21 } 22 } 23 ...... 24 }
那怎么知道栏目层数,或者怎么判断该栏目下面还有没有子栏目呢?
三、这里采用递归的方式
这样就可以不断重复查询本身的pid等于上一级id的数据,通过判断查到的数据是否为空来判断它有没有子栏目。
还有一个问题就是根据级别设置缩进,这样看着有层次感。那这个怎么实现呢?在php中有一个字符串函数str_repeat(),两个参数,第一个表示要重复的字符串,第二个是重复的次数。
代码片段如下:
//递归实现无限级菜单 public function tree2($pid=0,$level=0){ $cat = M('category'); $data = $cat ->where("parentid = $pid") ->field('id,catname,parentid') ->select(); $level ++; if(!empty($data)){ $tree = array(); foreach ($data as $val) { $val['catname'] = str_repeat('|—', $level-1).$val['catname']; $child = $this ->tree2($val[id],$level); $tree[] = array('self'=>$val,'child'=>$child,'level'=>$level); } } return $tree; } function test(){ $allcat = $this ->tree2(0); dump(json_encode($allcat)); }
上面tree2方法找到了所有栏目,并组装到tree数组中,tree是一个多维数组,现在要从数组中取出所有栏目名称catname,同样递归调用,代码如下:
//遍历找出所有catname function getcatname($array){ if(is_array($array)){ foreach ($array as $key=>$value ){ if(is_array($value)){ $this ->getcatname($value); }else{ $temp = array('key'=>$key,'value'=>$value); if ($temp['key'] == 'catname') { echo $temp['value']."<br/>"; } } } } } function test(){ $allcat = $this ->tree2(0); $this ->getcatname($allcat); }
页面显示效果图如下:
这样就实现了多级栏目的显示。