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

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

相关推荐
用户30745969820715 分钟前
🌟 PHP 接口(Interface)完全入门指南
php
欧的曼5 小时前
cygwin+php教程(swoole扩展+redis扩展)
开发语言·redis·后端·mysql·nginx·php·swoole
小楓12018 小时前
後端開發技術教學(二) 條件指令、循環結構、定義函數
服务器·后端·php
做一位快乐的码农10 小时前
基于vue的财务管理系统/基于php的财务管理系统
php
xiangweiqiang17 小时前
用phpstudy安装php8.2后报错:意思是找不到php_redis.dll拓展时
开发语言·php
fakaifa19 小时前
【同步更新】最新版龙兵名片装修版系统+小程序前端+搭建教程
前端·小程序·php·源码下载·龙兵名片·龙兵名片装饰
zh731421 小时前
laravel在cli模式下输出格式漂亮一些
microsoft·php·laravel
onejason1 天前
《PHP 爬虫实战指南:获取淘宝店铺详情》
前端·后端·php
用户3074596982071 天前
PHP 抽象类完全指南(含 PHP 8.4 新特性)
php
用户3074596982071 天前
📘 PHP 继承与静态机制深度解析
php