在Laravel 12中实现基于parent_id的树状数组

在Laravel中实现基于parent_id的树状数组,可以通过预加载所有节点并在内存中递归构建树结构来完成。以下是具体步骤和代码示例:

1. 创建模型及数据库迁移

迁移文件

php 复制代码
// 创建节点表
Schema::create('nodes', function (Blueprint $table) {
    $table->id();
    $table->unsignedBigInteger('parent_id')->nullable();
    $table->string('name');
    $table->timestamps();
});

模型

php 复制代码
// app/Models/Node.php
class Node extends Model
{
    protected $fillable = ['parent_id', 'name'];

    // 子节点关系
    public function children()
    {
        return $this->hasMany(Node::class, 'parent_id');
    }

    // 父节点关系
    public function parent()
    {
        return $this->belongsTo(Node::class, 'parent_id');
    }
}

2. 获取所有节点并构建树

控制器方法

php 复制代码
use App\Models\Node;

public function getTree()
{
    $nodes = Node::all();
    $groupedNodes = $nodes->groupBy('parent_id');

    $buildTree = function ($parentId = null) use (&$buildTree, $groupedNodes) {
        $result = [];
        if ($groupedNodes->has($parentId)) {
            foreach ($groupedNodes->get($parentId) as $node) {
                $node->children = $buildTree($node->id);
                $result[] = $node;
            }
        }
        return $result;
    };

    $tree = $buildTree();
    return response()->json($tree);
}

3. 使用API资源格式化输出(可选)

创建资源

bash 复制代码
php artisan make:resource NodeResource

定义资源结构

php 复制代码
// app/Http/Resources/NodeResource.php
class NodeResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'children' => NodeResource::collection($this->children),
        ];
    }
}

更新控制器

php 复制代码
use App\Http\Resources\NodeResource;

public function getTree()
{
    $nodes = Node::all();
    $groupedNodes = $nodes->groupBy('parent_id');

    $buildTree = function ($parentId = null) use (&$buildTree, $groupedNodes) {
        return collect($groupedNodes->get($parentId, []))->map(function ($node) use ($buildTree) {
            $node->children = $buildTree($node->id);
            return $node;
        });
    };

    $tree = $buildTree();
    return NodeResource::collection($tree);
}

4. 结果示例

生成的树状结构JSON如下:

json 复制代码
[
    {
        "id": 1,
        "name": "Root 1",
        "children": [
            {
                "id": 3,
                "name": "Child 1-1",
                "children": [
                    {
                        "id": 5,
                        "name": "Child 1-1-1",
                        "children": []
                    }
                ]
            },
            {
                "id": 4,
                "name": "Child 1-2",
                "children": []
            }
        ]
    },
    {
        "id": 2,
        "name": "Root 2",
        "children": []
    }
]

说明

  • 高效查询:仅需一次数据库查询获取所有节点,减少IO开销。
  • 内存构建 :通过groupBy按父ID分组,递归构建树结构,时间复杂度为O(n)。
  • 灵活扩展:可轻松添加排序逻辑或在资源中定制返回字段。
  • 避免循环:树状结构默认无循环,但存在循环引用时需额外处理。

此方法适用于大多数树状结构需求,如分类目录、组织架构等场景。在Laravel中实现基于parent_id的树状数组,可以通过预加载所有节点并在内存中递归构建树结构来完成。以下是具体步骤和代码示例:

1. 创建模型及数据库迁移

迁移文件

php 复制代码
// 创建节点表
Schema::create('nodes', function (Blueprint $table) {
    $table->id();
    $table->unsignedBigInteger('parent_id')->nullable();
    $table->string('name');
    $table->timestamps();
});

模型

php 复制代码
// app/Models/Node.php
class Node extends Model
{
    protected $fillable = ['parent_id', 'name'];

    // 子节点关系
    public function children()
    {
        return $this->hasMany(Node::class, 'parent_id');
    }

    // 父节点关系
    public function parent()
    {
        return $this->belongsTo(Node::class, 'parent_id');
    }
}

2. 获取所有节点并构建树

控制器方法

php 复制代码
use App\Models\Node;

public function getTree()
{
    $nodes = Node::all();
    $groupedNodes = $nodes->groupBy('parent_id');

    $buildTree = function ($parentId = null) use (&$buildTree, $groupedNodes) {
        $result = [];
        if ($groupedNodes->has($parentId)) {
            foreach ($groupedNodes->get($parentId) as $node) {
                $node->children = $buildTree($node->id);
                $result[] = $node;
            }
        }
        return $result;
    };

    $tree = $buildTree();
    return response()->json($tree);
}

3. 使用API资源格式化输出(可选)

创建资源

bash 复制代码
php artisan make:resource NodeResource

定义资源结构

php 复制代码
// app/Http/Resources/NodeResource.php
class NodeResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'children' => NodeResource::collection($this->children),
        ];
    }
}

更新控制器

php 复制代码
use App\Http\Resources\NodeResource;

public function getTree()
{
    $nodes = Node::all();
    $groupedNodes = $nodes->groupBy('parent_id');

    $buildTree = function ($parentId = null) use (&$buildTree, $groupedNodes) {
        return collect($groupedNodes->get($parentId, []))->map(function ($node) use ($buildTree) {
            $node->children = $buildTree($node->id);
            return $node;
        });
    };

    $tree = $buildTree();
    return NodeResource::collection($tree);
}

4. 结果示例

生成的树状结构JSON如下:

json 复制代码
[
    {
        "id": 1,
        "name": "Root 1",
        "children": [
            {
                "id": 3,
                "name": "Child 1-1",
                "children": [
                    {
                        "id": 5,
                        "name": "Child 1-1-1",
                        "children": []
                    }
                ]
            },
            {
                "id": 4,
                "name": "Child 1-2",
                "children": []
            }
        ]
    },
    {
        "id": 2,
        "name": "Root 2",
        "children": []
    }
]

说明

  • 高效查询:仅需一次数据库查询获取所有节点,减少IO开销。
  • 内存构建 :通过groupBy按父ID分组,递归构建树结构,时间复杂度为O(n)。
  • 灵活扩展:可轻松添加排序逻辑或在资源中定制返回字段。
  • 避免循环:树状结构默认无循环,但存在循环引用时需额外处理。

此方法适用于大多数树状结构需求,如分类目录、组织架构等场景。

相关推荐
t1987512811 小时前
使用深度神经网络解决无线网络资源分配问题的MATLAB实现
matlab·php·dnn
m0_4592524612 小时前
fastadmin动态渲染统计信息
开发语言·前端·javascript·php
AI成长日志12 小时前
【实用工具教程】Linux常用命令速查与实战场景:文件操作、进程管理与网络调试高频命令解析
linux·php
ccchen88812 小时前
适配帝国CMS 8.0:全新帝国CMS免登录采集发布插件
经验分享·爬虫·php·帝国cms自动采集发布插件·帝国cms8.0·帝国cms自动采集插件·帝国cms采集发布模块
vx-程序开发15 小时前
springboot在线装修管理系统-计算机毕业设计源码56278
java·c语言·spring boot·python·spring·django·php
幽络源小助理15 小时前
网页软件库源码(带1153条资源)-含详细搭建教程
php
博语小屋17 小时前
多路转接select、poll
开发语言·网络·c++·php
xuansec17 小时前
PHP 反序列化漏洞学习笔记(CTF向总结)
笔记·学习·php
liuxin_072517 小时前
Composer 安装
php·composer
共享家952719 小时前
Java入门( 异常 )
java·开发语言·php