在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)。
  • 灵活扩展:可轻松添加排序逻辑或在资源中定制返回字段。
  • 避免循环:树状结构默认无循环,但存在循环引用时需额外处理。

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

相关推荐
码云数智-大飞8 小时前
PHP 接口开发规范:统一返回格式、异常处理与参数校验
开发语言·php
dadaobusi8 小时前
仿真边界处理
开发语言·php
微学AI11 小时前
内网穿透的应用-把飞牛NAS变成家庭录像中心:EasyNVR部署与远程回放实战
开发语言·php
峥嵘life11 小时前
Android WiFi连接过程 wpa_supplicant 日志分析
android·开发语言·php
weixin_BYSJ198711 小时前
「课设设计」springboot校园超市助购系统26449 (附源码)
java·javascript·spring boot·python·django·flask·php
xuefeiniao12 小时前
CentOS + 宝塔服务器偶发 SSH、面板、网站全部无法访问排查记录(PHP-FPM 内存耗尽案例)
服务器·centos·ssh·php
神州世通1 天前
解密企业通信安全防线:Avaya Aura 三层安全架构深度解析
开发语言·php
AC赳赳老秦1 天前
企业工商公开信息采集分析:OpenClaw 批量查询企业工商信息,生成企业画像报告
大数据·开发语言·python·自动化·php·deepseek·openclaw
AC赳赳老秦1 天前
司法公开数据采集应用:OpenClaw 抓取裁判文书公开信息,批量整理同类参考案例
java·大数据·python·数据挖掘·数据分析·php·openclaw
Vae_Mars1 天前
C#中多线程异步操作的方法-Parallel.ForEachAsync
开发语言·c#·php