You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel Eloquent模型create时递归自动加载所有关联的原因

问题场景

项目模型关联规则如下:

  • Customer模型与Order模型为一对多关联(Customer has many Orders)
  • Customer模型与Detail模型为一对一关联(Customer has one Detail)

执行如下代码创建新订单:

$order  = Order::create($data);

返回的$order对象自动递归加载了所有层级关联,数据结构如下:

Order
- order_id
- product_id
- purchase_date
- customer_id
- customer
    - customer_id
    - customer_name
    - order
         - order_id
         - product_id
         - purchase_date
         - customer_id
    - detail
         - detail_id
         - customer_id
         - address
         - phone

运行环境为Laravel 5.5 + PHP 7.2。

触发原因

核心原因是模型全局预加载配置$with出现了循环引用,结合Laravel 5.5的模型加载逻辑触发了递归加载:

  1. Order模型中配置了全局预加载属性protected $with = ['customer'];,所有返回Order模型实例的操作(包括create()新建、find()查询、get()列表查询),都会自动加载声明的customer关联。
  2. 同时Customer模型中又配置了protected $with = ['orders', 'detail'];,所有返回Customer模型实例的操作,都会自动加载关联的orders和detail数据。
  3. 两者形成加载死循环:Order实例触发加载Customer → 加载完成的Customer实例触发加载Order → 拿到的Order实例再次触发加载Customer,递归执行直到达到PHP嵌套限制终止,最终返回多层嵌套的关联结构。

如果没有配置$with属性,可排查是否在模型的boot方法、created/retrieved等模型事件中手动编写了递归调用load()加载关联的逻辑,这类写法也会触发相同问题。

修复方式
  • 移除关联模型中互相引用的全局$with配置,禁止在两个互相关联的模型中同时将对方加入全局预加载列表,需要关联数据时调用with()方法按需预加载即可。
  • 若必须保留部分全局预加载规则,需打断循环引用:例如Order中保留全局加载Customer,Customer中就不要全局加载Order,仅保留全局加载Detail即可。
  • 若为事件/boot方法中手动写的加载逻辑,删除多余的递归load()调用即可。

内容的提问来源于stack exchange,提问作者Sagar Gautam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 07:54:33