PHP实现无限级分类分析

最近在写一个博客,由于博主栏目比较多,所以二级栏目已经满足不了,所以需要实现三级菜单,下面我们就一点点的来分析。

这是我最后实现的效果图:


由于需要实现无限级分类,所以我们需要知道它的子栏目有什么?

最后实现的数组是这样的形式:

Array
(
    [0] => Array
        (
            [category_id] => 1
            [category_name] => 关于我
            [category_pid] => 0
            [category_addtime] => 0
            [category_order] => 0
        )

    [1] => Array
        (
            [category_id] => 2
            [category_name] => 生活随笔
            [category_pid] => 0
            [category_addtime] => 0
            [category_order] => 0
        )

    [2] => Array
        (
            [category_id] => 3
            [category_name] => 文章类别
            [category_pid] => 0
            [category_addtime] => 0
            [category_order] => 0
            [category_child] => Array
                (
                    [0] => Array
                        (
                            [category_id] => 4
                            [category_name] => Linux服务器
                            [category_pid] => 3
                            [category_addtime] => -28800
                            [category_order] => 1
                            [category_child] => Array
                                (
                                    [0] => Array
                                        (
                                            [category_id] => 5
                                            [category_name] => linux优化
                                            [category_pid] => 4
                                            [category_addtime] => 0
                                            [category_order] => 0
                                        )

                                    [1] => Array
                                        (
                                            [category_id] => 6
                                            [category_name] => 虚拟化
                                            [category_pid] => 4
                                            [category_addtime] => 1478228220
                                            [category_order] => 0
                                        )

                                    [2] => Array
                                        (
                                            [category_id] => 7
                                            [category_name] => Mysql优化与开发
                                            [category_pid] => 4
                                            [category_addtime] => 1478188800
                                            [category_order] => 0
                                        )

                                    [3] => Array
                                        (
                                            [category_id] => 8
                                            [category_name] => 高可用与虚拟化
                                            [category_pid] => 4
                                            [category_addtime] => 1478394120
                                            [category_order] => 0
                                        )

                                )

                        )

                    [1] => Array
                        (
                            [category_id] => 15
                            [category_name] => Mysql
                            [category_pid] => 3
                            [category_addtime] => 1480555980
                            [category_order] => 0
                            [category_child] => Array
                                (
                                    [0] => Array
                                        (
                                            [category_id] => 16
                                            [category_name] => 优化
                                            [category_pid] => 15
                                            [category_addtime] => 1480555980
                                            [category_order] => 0
                                        )

                                    [1] => Array
                                        (
                                            [category_id] => 17
                                            [category_name] => Sql编程
                                            [category_pid] => 15
                                            [category_addtime] => 1480556040
                                            [category_order] => 8
                                        )

                                )

                        )

                )

        )

)

那么我们从数据库中取出来的二维数组如何才能变成上面这样的数组呢?

举例:

我们要把下面这个二维数组实现成上面那种形式。

$arr=array(  
	array('id'=>'1','name'=>'北京','pid'=>'0'),  
	array('id'=>'2','name'=>'上海','pid'=>'0'),  
	array('id'=>'3','name'=>'浦东','pid'=>'2'),  
	array('id'=>'4','name'=>'朝阳','pid'=>'1'),  
	array('id'=>'5','name'=>'广州','pid'=>'0'),  
	array('id'=>'6','name'=>'三里屯','pid'=>'4'), 
	array('id'=>'7','name'=>'广东','pid'=>'5'), 
	array('id'=>'8','name'=>'三里','pid'=>'4'),
	array('id'=>'10','name'=>'小胡同','pid'=>'8')
	); 
第一种方法:利用数组的索引与主键的id号相同来查找子栏目,首先为数组加上索引:

$arr=array(  
	1=>array('id'=>'1','name'=>'北京','pid'=>'0'),  
	2=>array('id'=>'2','name'=>'上海','pid'=>'0'),  
	3=>array('id'=>'3','name'=>'浦东','pid'=>'2'),  
	4=>array('id'=>'4','name'=>'朝阳','pid'=>'1'),  
	5=>array('id'=>'5','name'=>'广州','pid'=>'0'),  
	6=>array('id'=>'6','name'=>'三里屯','pid'=>'4'), 
	7=>array('id'=>'7','name'=>'广东','pid'=>'5'), 
	8=>array('id'=>'8','name'=>'三里','pid'=>'4'),
	10=>array('id'=>'10','name'=>'小胡同','pid'=>'8')
	); 
利用索引的下标,判断该栏目是否存在父栏目,如果存在就把该栏目放到父栏目的son子数组里面
function generateTree($items){
    $tree = array();
    foreach($items as $item){
    	//判断是否有数组的索引==
        if(isset($items[$item['pid']])){     //查找数组里面是否有该分类  如 isset($items[0])  isset($items[1])
            $items[$item['pid']]['son'][] = &$items[$item['id']]; //上面的内容变化,$tree里面的值就变化
        }else{
            $tree[] = &$items[$item['id']];   //把他的地址给了$tree
        }  
    }
    return $tree;
}	
上面这个程序有一个主要问题,数组的索引是我们手动添加的?那我们可不可以自动添加数组索引呢?当然可以,下面这个程序就实现了,自动为数组添加索引然后再把子栏目放到父栏目的son数组中,思想和上面的程序是一样的

function make_tree($list,$pk='id',$pid='pid',$child='_child',$root=0){
    $tree=array(); 
    $packData=array();
    foreach ($list as  $data) {
   
    	//转换为带有主键id的数组
        $packData[$data[$pk]] = $data; //$packData[1]=$data; $packData[2]=$data 
    }
    foreach ($packData as $key =>$val){     
        if($val[$pid]==$root){   //代表跟节点       
            $tree[]=& $packData[$key];
        }else{
            //找到其父类
            $packData[$val[$pid]][$child][]=& $packData[$key];
        }
    }
    return $tree;
}
第二种方法:使用递归来查找子栏目

思想:使用递归来查找每个栏目中的子栏目,直到找到最后一个子栏目以后再一层层往外运行调试的话,可以打印$tree看一下,会发现,第一个打印的不是最后一个子栏目,而是三里屯,然后是北京的最后一个子栏目小胡同,这个是因为递归的时候,三里屯和三里在一个层级,三里屯下面没有子栏目直接跳出循环输出了,所以三里屯会在第一个$tree中,,为了方便理解,可以打印$tree去观察数组的变化

array('id'=>'6','name'=>'三里屯','pid'=>'4'), 
function make_tree1($list,$pk='id',$pid='pid',$child='_child',$root=0){
    $tree=array();
    foreach($list as $key=> $val){
        if($val[$pid]==$root){
            //获取当前$pid所有子类 
                unset($list[$key]);
                if(! empty($list)){
                    $child=make_tree1($list,$pk,$pid,$child,$val[$pk]); //来来来 找北京的子栏目 递归 空
                    
                    if(!empty($child)){
                        $val['_child']=$child;
                    }
                }              
                $tree[]=$val;
        }
    }   
    return $tree;
}
为了更好的理解递归,大家可以找一个小程序测试一下例如下面这个求和的程序
大家可以分析一下$n的输出从2,3 .....10,而不是从10,9----2,我从这个程序才理解了一下上面那个程序的递归是如何实现的,总之:递归是很有意思的一个东西,希望大家好好理解
<?php
        function sum($n){
            $a=0;
            if($n>1){   
                $a=sum($n-1)+$n;

                /*if($n>5){
                    echo "$n <br />" ;
                }*/
                echo "$n<br />";
            }else{
                $a=1;
            }
            
            return $a;
        }
        echo sum(10);








  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值