Laravel递归循环处理树形结构数据

小辰大大_2100

小辰大大_2100

2026-06-16

979人浏览

原创

直接用 with('children') 会爆栈或查出重复数据,是因为递归加载未设终止条件,eloquent 的 with() 不支持无限嵌套,且未做循环检测、id 缓存或软删除兼容处理。

laravel递归循环处理树形结构数据

为什么直接用 with('children') 会爆栈或查出重复数据

这不是 Eloquent 的 bug,而是递归加载没设终止条件的必然结果。Eloquent 的 with() 本身不支持无限嵌套,写成 with('children.children.children') 是硬编码层级,一旦真实树深超过预设值,漏掉的节点就查不到;若改成闭包递归调用自身(比如在 scope 里反复调 withChildren()),PHP 会不断新建查询上下文,最终内存耗尽或达到 xdebug.max_nesting_level 限制报错。

常见错误现象包括:Fatal error: Allowed memory size exhausted、Maximum function nesting level reached、返回结果里同一节点出现多次——根本原因是没缓存已处理过的 ID,或没过滤已加入树的节点。

  • 别在模型的 accessor 或 scope 里隐式触发递归查询,例如 getTreeAttribute 中又调 $this->children
  • 不要依赖 with() 自动推导关系深度,它不会帮你做循环检测
  • 如果用了软删除,children() 关联默认不包含已软删节点,树会在断点处截断,得显式加 withTrashed()

用 buildTree() 手动组装前必须检查三件事

这个函数看似简单,但 80% 的空数组、Array to string conversion 错误都源于底层数据没对齐。核心不是“怎么写递归”,而是“怎么让 PHP 能准确把子节点挂到父节点下”。

Laravel Creem Agent
Laravel Creem Agent

Creem 支付商店助理 — 查询订阅、客户、交易、产品,执行心跳检查,管理本地 Laravel支付商店。

下载
  • id 和 parent_id 字段类型必须一致:都为 unsignedBigInteger,且 PHP 中用 (int) 强转后再比较,避免字符串 "1" 匹配整数 1 失败
  • parent_id 必须允许为 null(根节点),不能设 NOT NULL DEFAULT 0,否则插入根节点时违反约束
  • 先用 groupBy('parent_id') 把扁平集合分组,而不是每次 filter() 遍历全量数据——后者是 O(n²),几百条数据就明显卡顿

示例关键片段:

public function buildTree($groups, $parentId = null)
{
    $items = $groups->get($parentId, collect());
    return $items->map(function ($item) use ($groups) {
        return $item->merge(['children' => $this->buildTree($groups, $item->id)]);
    });
}

什么时候该放弃 buildTree() 改用 spatie/laravel-nested-set

不是功能强就该上,而是当业务动作开始“动”树结构时,buildTree() 就从工具变成瓶颈。它适合读多写少、层级浅、总量小(

  • 移动一个节点,邻接表方案要更新该节点所有后代的 parent_id,N 层就要 N 次 UPDATE
  • spatie/laravel-nested-set 用 lft/rgt 字段,移动只需改 4 个数字,性能稳定
  • 它自带 isDescendantOf()、getSiblings() 等方法,不用自己拼 whereRaw('path LIKE ?')
  • 迁移成本明确:运行 php artisan vendor:publish --provider="Spatie\NestedSet\NestedSetServiceProvider" --tag=migrations,再 php artisan migrate

用 laravel-adjacency-list 做 CTE 递归查询要注意兼容性

这个包本质是帮你生成 MySQL 8.0+ 或 PostgreSQL 的 WITH RECURSIVE SQL,不是纯 PHP 方案。它能一次查出带 depth、path、is_cycle 的完整子树,但前提是你的数据库版本撑得住。

  • MySQL 必须 ≥ 8.0,5.7 不支持 WITH RECURSIVE,强行用会报 SQLSTATE[42000]: Syntax error
  • 开启 cycle detection 后,查询会自动加 CYCLE 子句并返回 is_cycle 字段,但需确保模型中定义了 getPathKeyName(),否则路径解析失败
  • 它不替代数据校验:DB 层仍可能存入循环数据(如 A→B→C→A),CTE 只负责查的时候发现并中断,不阻止写入

真正容易被忽略的是:CTE 查询结果是扁平集合,不是嵌套对象。你得自己按 depth 或 path 再组织一次,或者前端直接消费扁平结构 + CSS 缩进。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

laravel

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

2023.09.01

10244

6

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.11

6041

5

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.11

2095

5

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

2023.10.23

3808

4

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

2023.10.23

4494

6

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.03

3531

9

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.09

5037

8

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.13

3942

8

sprintf函数用法详解
sprintf函数用法详解

sprintf函数的用法:1、格式化字符串;2、指定输出宽度和精度;3、返回值。更多关于sprintf函数用法详解的内容,大家可以阅读下面的文章。

2023.11.27

11902

4

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
如何安装 Composer
如何安装 Composer

共1课时 | 201人学习

Composer手册
Composer手册

共0课时 | 0人学习