php无限分类形成列表树并显示子栏目总数

发布时间 2023-11-26 15:39:56作者: 码农骆驼

https://blog.csdn.net/rghanbing4/article/details/51284131

 

<pre name="code" class="php"><pre name="code" class="php"><?php
    $arr = array(
        array('id' => 111, 'pid' => 0, 'name' => '江西省'),
        array('id' => 5, 'pid' => 2, 'name' => '鸡西市'),
        array('id' => 2, 'pid' => 0, 'name' => '黑龙江省'),
        array('id' => 3, 'pid' => 111, 'name' => '南昌市'),
        array('id' => 6, 'pid' => 4, 'name' => '香坊区'),
        array('id' => 27, 'pid' => 4, 'name' => '南岗区'),
        array('id' => 8, 'pid' => 6, 'name' => '和兴路'),
        array('id' => 9, 'pid' => 27, 'name' => '西大直街'),
        array('id' => 10, 'pid' => 8, 'name' => '东北林业大学'),
        array('id' => 11, 'pid' => 9, 'name' => '哈尔滨工业大学'),
        array('id' => 12, 'pid' => 8, 'name' => '哈尔滨师范大学'),
        array('id' => 13, 'pid' => 111, 'name' => '赣州市'),
        array('id' => 14, 'pid' => 13, 'name' => '赣县'),
        array('id' => 15, 'pid' => 13, 'name' => '于都县'),
        array('id' => 16, 'pid' => 14, 'name' => '茅店镇'),
        array('id' => 17, 'pid' => 14, 'name' => '大田乡'),
        array('id' => 18, 'pid' => 16, 'name' => '义源村'),
        array('id' => 19, 'pid' => 16, 'name' => '上坝村')
    );
    static $_arr2 = array();       //用于存放整理好的数据
    /**
     * 对数组按照子父类顺序整理,并且直接获取栏目的所有子栏目数
     * @param array $_arr2 用于存放整理结果的数组
     * @param array $arr 需要整理的数组
     * @param number $pid 父栏目id,会递归找出该父亲栏目下的所有子栏目
     * @param number $level 第几级
     * @return array $num 子栏目数
     */
    function getTreeAndNum(&$_arr2, $arr, $pid=0, $level=0 ,$isClear=FALSE){
        if($isClear)
           $_arr2 = array();
        $num = 0;
        foreach($arr as $k => $v){
            if($v['pid'] == $pid){
                $v['level'] = $level;
                $_arr2[$v['id']] = $v;
                $num ++;
                $allnum = getTreeAndNum($_arr2, $arr, $v['id'], $level+1);
                $_arr2[$v['id']]['num'] = $allnum;
                $num = $num + $allnum;
            }
        }
        return $num;
    }
    
    /**
     * 对数组按照子父类顺序整理
     * @param array $arr 需要整理的数组
     * @param number $pid 父栏目id
     * @param number $level 第几级
     * @return array $_arr 整理好的数组
     */
    function getTree($arr, $pid=0, $level=0, $isClear=FALSE){
        //因为不断调用自己的时候,会不断开辟新的空间,空间与空间之间的变量是不能共享的,可//以存放到静态数组中,实现共享
        static $_arr = array();
        if($isClear)
            $_arr = array();
        foreach($arr as $k => $v){
            if($v['pid'] == $pid){
                $v['level'] = $level;
                $_arr[] = $v;
                getTree($arr, $v['id'], $level+1);
            }
        }
        return $_arr;
    }
    
    /**
     * 获取一个栏目的所有子栏目数
     * @param array $arr 数组
     * @param number $catId 父栏目
     * @return number $_ret 一个栏目的子栏目数
     */
    function getChildrenNums($arr, $catId, $isClear=FALSE)
    {
        static $_ret = 0;  
        if($isClear)
           $_ret = 0;
        foreach ($arr as $k => $v)
        {
            if($v['pid'] == $catId)
            {
                $_ret++;
                
                getChildrenNums($arr, $v['id']);
            }
        }
        return $_ret;
    }
    /**
     * 获取列表树,此方法先遍历整理好的数组,在遍历的过程中再次去调用函数获取该栏目的所有子栏目数目
     * @param unknown $arr 数组
     */
    function getList($arr){
        
        foreach($arr as $k => $v){
            echo str_repeat('-', 4*$v['level']).$v['name'].'('.getChildrenNums($arr, $v['id'], TRUE).')'.'<br/>';
        }
    }
    
    function getNewList($arr){
        foreach($arr as $k => $v){
            echo str_repeat('-', 4*$v['level']).$v['name'].'('.$v['num'].')'.'<br/>';
        }
    }
    /**
     * 返回当前的时间,以秒为单位
     * @return number
     */
    function getMicTime(){
        return time();
    }
    
    
    
    /**
     * 性能测试,由于数据量比较小,循环后才能见到差距,数据量大的话,差距会明显些
     * 总结来说,方案2的效率会高些
     */
    echo '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
    /****************方案1**********************/
    
    $time1 = getMicTime();
    for($i = 0; $i < 4000; $i++){
        $arr = getTree($arr, $pid=0, $level=0, TRUE);
        getList($arr);
    }
    $time2 = getMicTime();
    echo '方案1的性能为:'.($time2-$time1).'<br>';
    
    
    /****************方案2**********************/
     $time3 = getMicTime();
     for($i = 0; $i < 4000; $i++){
         getTreeAndNum($_arr2, $arr, $pid=0, $level=0 ,TRUE);
         getNewList($_arr2);
     }
     $time4 = getMicTime();
    echo '方案2的性能为:'.($time4-$time3).'<br>';

 

如果要对列表的某个数据字段累加和:

static $result = [];
self::_getTotalCount($result, $list, 0, 0 ,TRUE);   

 private static function _getTotalCount(&$result, $arr, $pid=0, $level=0 ,$isClear=FALSE){
        if($isClear){
            $result = [];
        }

        $num = 0;
        foreach($arr as $k => $v){
            if($v['pid'] == $pid){
                $v['level'] = $level;
                $result[$v['id']] = $v;
                $num += $v['count'];
                $all_num = self::_getTotalCount($result, $arr, $v['id'], $level+1);
                $result[$v['id']]['total'] = $all_num + $v['count'];
                $num = $num + $all_num;
            }
        }
        return $num;
    }