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);
    }

  页面显示效果图如下:

    

  这样就实现了多级栏目的显示。

posted @ 2016-11-30 15:41  菜乌  阅读(10576)  评论(0编辑  收藏  举报