您的当前位置:首页>全部文章>文章详情

php列表数据转成树形结构

发表于:2024-04-19 16:36:04浏览:170次TAG: #PHP #树形

前言

本文将详细介绍PHP把列表转成树形结构,并提供整理的源码和通过示例代码进行说明。

源数据

[
    {
        "id": 1,
        "pid": 0,
        "title": "Frontend"
    },
    {
        "id": 2,
        "pid": 0,
        "title": "API Interface"
    },
    {
        "id": 3,
        "pid": 1,
        "title": "User Module"
    },
    {
        "id": 4,
        "pid": 2,
        "title": "User Module"
    },
    {
        "id": 7,
        "pid": 3,
        "title": "User Center"
    },
    {
        "id": 8,
        "pid": 3,
        "title": "Profile"
    }
]

调用

$tree = \app\common\utils\Tree::makeTree($list);
// 输出=>
//[
//    {
//        "id": 1,
//        "pid": 0,
//        "title": "Frontend",
//        "level": 0,
//        "expanded": false,
//        "children": [
//            {
//                "id": 3,
//                "pid": 1,
//                "title": "User Module",
//                "level": 1,
//                "expanded": false,
//                "children": [
//                    {
//                        "id": 7,
//                        "pid": 3,
//                        "title": "User Center",
//                        "level": 2,
//                        "leaf": true
//                    },
//                    {
//                        "id": 8,
//                        "pid": 3,
//                        "title": "Profile",
//                        "level": 2,
//                        "leaf": true
//                    }
//                ]
//            }
//        ]
//    },
//    {
//        "id": 2,
//        "pid": 0,
//        "title": "API Interface",
//        "level": 0,
//        "expanded": false,
//        "children": [
//            {
//                "id": 4,
//                "pid": 2,
//                "title": "User Module",
//                "level": 1,
//                "leaf": true
//            }
//        ]
//    }
//]

<?php
namespace app\common\utils;
/**
 * 树形
 */
class Tree{

    protected static $config = array(
        /* 主键 */
        'primary_key'     => 'id',
        /* 父键 */
        'parent_key'      => 'pid',
        /* 展开属性 */
        'expanded_key'  => 'expanded',
        /* 叶子节点属性 */
        'leaf_key'      => 'leaf',
        /* 孩子节点属性 */
        'children_key'  => 'children',
        /* 等级属性 */
        'level_key'  => 'level',
        /* 是否展开子节点 */
        'expanded'        => false,
        /* 重定义字段名 */
        'props' => []
    );

    /* 结果集 */
    protected static $result = array();

    /* 层次暂存 */
    protected static $level = array();
    /**
     * @name 生成树形结构
     * @param array 二维数组
     * @return mixed 多维数组
     */
    public static function makeTree($data,$options=array()){
        if (!$data) {
            return [];
        }
        $dataset = self::buildData($data,$options);
        $treeData = self::makeTreeCore(0,$dataset,'normal');
        $results = self::treeBeautify($treeData);
        return $results;
    }
    /**
     * 树形数据美化
     * @param $data
     * @return array
     */
    public static function treeBeautify($data)
    {
        $props = self::$config['props'];
        if (!$props) {
            return $data;
        }
        $children_key_old = self::$config['children_key'];
        $children_key = $props[$children_key_old] ?? $children_key_old;
        $results = [];
        foreach ($data as $key=>$item) {
            $children = [];
            if (!empty($item[$children_key_old])) {
                $children = self::treeBeautify($item[$children_key_old]);
            }
            $new_item = [];
            foreach ($props as $old_key=>$new_key) {
                if (isset($item[$old_key])) {
                    $new_item[$new_key] = $item[$old_key];
                }
            }
            if ($new_item) {
                $children && $new_item[$children_key] = $children;
                $results[] = $new_item;
            }
        }
        return $results;
    }
    /* 生成线性结构, 便于HTML输出, 参数同上 */
    public static function makeTreeForHtml($data,$options=array()){
        if (!$data) {
            return [];
        }
        $dataset = self::buildData($data,$options);
        $r = self::makeTreeCore(0,$dataset,'linear');
        return $r;
    }

    /* 格式化数据, 私有方法 */
    private static function buildData($data,$options){
        $config = array_merge(self::$config,$options);
        self::$config = $config;
        extract($config);

        $r = array();
        foreach($data as $item){
            $id = $item[$primary_key];
            $parent_id = $item[$parent_key];
            $r[$parent_id][$id] = $item;
        }

        return $r;
    }

    /* 生成树核心, 私有方法  */
    private static function makeTreeCore($index,$data,$type='linear')
    {
        extract(self::$config);
        foreach($data[$index] as $id=>$item)
        {
            if($type=='normal'){

                $parent_id = $item[$parent_key];
                self::$level[$id] = $index==0?0:self::$level[$parent_id]+1;
                $item[$level_key] = self::$level[$id];

                if(isset($data[$id]))
                {
                    $item[$expanded_key]= self::$config['expanded'];
                    $item[$children_key]= self::makeTreeCore($id,$data,$type);
                }
                else
                {
                    $item[$leaf_key]= true;
                }
                $r[] = $item;
            }else if($type=='linear'){
                $parent_id = $item[$parent_key];
                self::$level[$id] = $index==0?0:self::$level[$parent_id]+1;
                $item['level'] = self::$level[$id];
                self::$result[] = $item;
                if(isset($data[$id])){
                    self::makeTreeCore($id,$data,$type);
                }

                $r = self::$result;
            }
        }
        return $r;
    }
}