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

news2025/5/10 0:01:25

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

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

迁移文件

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

模型

// 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. 获取所有节点并构建树

控制器方法

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资源格式化输出(可选)

创建资源

php artisan make:resource NodeResource

定义资源结构

// 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),
        ];
    }
}

更新控制器

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如下:

[
    {
        "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. 创建模型及数据库迁移

迁移文件

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

模型

// 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. 获取所有节点并构建树

控制器方法

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资源格式化输出(可选)

创建资源

php artisan make:resource NodeResource

定义资源结构

// 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),
        ];
    }
}

更新控制器

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如下:

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2371882.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaWeb:后端web基础(TomcatServletHTTP)

一、今日内容 二、Tomcat 介绍与使用 介绍 基本使用 小结 配置 配置 查找进程 三、Servlet 什么是Servlet 快速入门 需求 步骤 1.新建工程-模块(Maven) 2.修改打包方式-war 3.编写代码 /*** 可以选择继承HttpServlet*/ WebServlet("/hello&q…

缓存(1):三级缓存

三级缓存是指什么 我们常说的三级缓存如下: CPU三级缓存Spring三级缓存应用架构(JVM、分布式缓存、db)三级缓存 CPU 基本概念 CPU 的访问速度每 18 个月就会翻 倍,相当于每年增⻓ 60% 左右,内存的速度当然也会不断…

Cursor —— AI编辑器 使用详解

Cursor - The AI Code Editor 一、Cursor 是什么? Cursor 是一款优秀的AI代码编辑器,它内置了 Deepseek-R1、GPT-4、Claude等 AI 模型。 简单说,就是:Cursor VS Code 编辑器 AI 大模型 Cursor 功能特性(代码补全、…

Pytorch-CUDA版本环境配置

Pytorch-CUDA版本环境配置 电脑如果是Windows平台下的Nvidia GPU的用户,需配置Pytorch的CUDA版本,分为三步: 1. 安装或更新NVIDA显卡驱动 官方驱动下载地址: https://www.nvidia.cn/Download/index.aspx?langcn 2. 安装CUDA Too…

OpenCV 图形API(77)图像与通道拼接函数-----对图像进行几何变换函数remap()

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 对图像应用一个通用的几何变换。 函数 remap 使用指定的映射对源图像进行变换: dst ( x , y ) src ( m a p x ( x , y ) , m a p y…

Spring AI 入门(持续更新)

介绍 Spring AI 是 Spring 项目中一个面向 AI 应用的模块&#xff0c;旨在通过集成开源框架、提供标准化的工具和便捷的开发体验&#xff0c;加速 AI 应用程序的构建和部署。 依赖 <!-- 基于 WebFlux 的响应式 SSE 传输 --> <dependency><groupId>org.spr…

QUIC协议优化:HTTP_3环境下的超高速异步抓取方案

摘要 随着 QUIC 和 HTTP/3 的普及&#xff0c;基于 UDP 的连接复用与内置加密带来了远超 HTTP/2 的性能提升&#xff0c;可显著降低连接握手与拥塞恢复的开销。本文以爬取知乎热榜数据为目标&#xff0c;提出一种基于 HTTPX aioquic 的异步抓取方案&#xff0c;并结合代理 IP设…

uni-app实现完成任务解锁拼图功能

界面如下 代码如下 <template><view class"puzzle-container"><view class"puzzle-title">任务进度 {{completedCount}}/{{totalPieces}}</view><view class"puzzle-grid"><viewv-for"(piece, index) in…

数据链路层(MAC 地址)

目录 一、前言&#xff1a; 二、以太网&#xff1a; 三、MAC 地址的作用&#xff1a; 四、ARP协议&#xff1a; 一、前言&#xff1a; 数据链路层主要负责相邻两个节点之间的数据传输&#xff0c;其中&#xff0c;最常见数据链路层的协议有 以太网&#xff08;通过光纤 / 网…

基于DQN的自动驾驶小车绕圈任务

1.任务介绍 任务来源: DQN: Deep Q Learning &#xff5c;自动驾驶入门&#xff08;&#xff1f;&#xff09; &#xff5c;算法与实现 任务原始代码: self-driving car 最终效果&#xff1a; 以下所有内容&#xff0c;都是对上面DQN代码的改进&#…

【Linux】Linux工具(1)

3.Linux工具&#xff08;1&#xff09; 文章目录 3.Linux工具&#xff08;1&#xff09;Linux 软件包管理器 yum什么是软件包关于 rzsz查看软件包——yum list命令如何安装软件如何卸载软件补充——yum如何找到要安装软件的下载地址 Linux开发工具Linux编辑器-vim使用1.vim的基…

基于 Spring Boot 瑞吉外卖系统开发(十一)

基于 Spring Boot 瑞吉外卖系统开发&#xff08;十一&#xff09; 菜品启售和停售 “批量启售”、“批量停售”、操作列的售卖状态绑定单击事件&#xff0c;触发单击事件时&#xff0c;最终携带需要修改售卖状态的菜品id以post请求方式向“/dish/status/{params.status}”发送…

深入理解负载均衡:传输层与应用层的原理与实战

目录 前言1. 传输层&#xff08;Layer 4&#xff09;负载均衡1.1 工作层级与核心机制1.2 实现方式详解1.3 优缺点分析1.4 典型实现工具 2. 应用层&#xff08;Layer 7&#xff09;负载均衡2.1 工作层级与核心机制2.2 实现方式解析2.3 优缺点分析2.4 常用实现工具 3. Layer 4 与…

WPF之Slider控件详解

文章目录 1. 概述2. 基本属性2.1 值范围属性2.2 滑动步长属性2.3 刻度显示属性2.4 方向属性2.5 选择范围属性 3. 事件处理3.1 值变化事件3.2 滑块拖动事件 4. 样式和模板自定义4.1 基本样式设置4.2 控件模板自定义 5. 数据绑定5.1 绑定到ViewModel5.2 同步多个控件 6. 实际应用…

企业微信自建消息推送应用

企业微信自建应用来推送消息 前言 最近有个给特定部门推送消息的需求&#xff0c;所以配置一个应用专门用来推送消息。实现过程大致为&#xff1a;服务器生成每天的报告&#xff0c;通过调用API来发送消息。以前一直都是发邮件&#xff0c;整个邮箱里全是报告文件&#xff0c…

日志之ClickHouse部署及替换ELK中的Elasticsearch

文章目录 1 ELK替换1.1 Elasticsearch vs ClickHouse1.2 环境部署1.2.1 zookeeper 集群部署1.2.2 Kafka 集群部署1.2.3 FileBeat 部署1.2.4 clickhouse 部署1.2.4.1 准备步骤1.2.4.2 添加官方存储库1.2.4.3 部署&启动&连接1.2.4.5 基本配置服务1.2.4.6 测试创建数据库和…

解构与重构:自动化测试框架的进阶认知之旅

目录 一、自动化测试的介绍 &#xff08;一&#xff09;自动化测试的起源与发展 &#xff08;二&#xff09;自动化测试的定义与目标 &#xff08;三&#xff09;自动化测试的适用场景 二、什么是自动化测试框架 &#xff08;一&#xff09;自动化测试框架的定义 &#x…

DockerDesktop替换方案

背景 由于DockerDesktop并非开源软件&#xff0c;如果在公司使用&#xff0c;可能就有一些限制&#xff0c;那是不是除了使用DockerDesktop外&#xff0c;就没其它办法了呢&#xff0c;现在咱们来说说替换方案。 WSL WSL是什么&#xff0c;可自行百度&#xff0c;这里引用WS…

力扣热题100之搜索二维矩阵 II

题目 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。 每列的元素从上到下升序排列。 代码 方法一&#xff1a;直接全体遍历 这个方法很直接&#xff0c;但是居然没有超时&#xff0c…

docker操作镜像-以mysql为例

Docker安装使用-CSDN博客 docker操作镜像-以mysql为例 当安装一个新的镜像时可以登录https://hub.docker.com/直接搜索想要安装的镜像&#xff0c;查看文档 1&#xff09;拉取镜像 docker pull mysql 或者 docker pull mysql:版本号 然后直接跳到第4&#xff09;步即可 2…