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

Laravel中create/update前调用with()的技术影响及问题咨询

Laravel中create/update前使用with()的问题解析

场景1:关联查询构造器链式调用with()->create()

你这段代码里,$vehicle->stkRecords()返回的是关联查询构造器,调用with(['vehicle:id,name'])是给这个查询构造器添加预加载规则,但create()方法的逻辑是直接插入数据,然后返回新创建的StkRecord模型实例——这个过程不会触发查询构造器的查询操作,预加载规则完全没生效。

所以返回的$item是刚创建的模型,没有加载vehicle关联数据,最终Resource返回结果里自然缺失这部分内容。

场景2:模型实例链式调用with()->update()

$item是已存在的StkRecord模型实例,调用with(['vehicle:id,name'])会生成一个新的查询构造器,但后续的update()是执行批量更新操作(注意:这里的update不是针对当前模型实例的属性更新,而是基于查询构造器的批量更新),而且更新后你返回的还是原来的$item实例:

  • 原实例的属性还是更新前的旧值
  • 预加载规则根本没作用到这个实例上

所以返回的Resource同样没有vehicle关联数据。

为什么这种写法被允许?

Laravel的查询构造器和模型支持链式调用,with()是合法的链式方法,只要语法符合规则,框架就不会阻止你这么写——它不会在编译或运行时检查你链式调用的逻辑是否合理,只会执行每一步方法的既定逻辑。所以这种语法合法但逻辑无效的写法是被允许的。

正确的实现方式

场景1的修正

要么创建后手动加载关联,要么把预加载逻辑放到Resource里:

// 方式1:创建后加载关联
$item = $vehicle->stkRecords()->create($request->validated());
$item->load(['vehicle:id,name']);

return response()->json([
    'data' => new StkRecordResource($item)
]);
// 方式2:在Resource中定义预加载(更推荐)
// StkRecordResource.php
public function toArray($request)
{
    return [
        // 其他字段
        'vehicle' => new VehicleResource($this->whenLoaded('vehicle')),
    ];
}

// 控制器中创建后加载关联
$item = $vehicle->stkRecords()->create($request->validated());
return response()->json([
    'data' => new StkRecordResource($item->load('vehicle:id,name'))
]);

场景2的修正

更新后重新加载模型及关联,或者手动加载关联:

// 方式1:更新后重新获取带关联的模型
$item->update($request->validated());
$item = $item->fresh(['vehicle:id,name']);

return response()->json([
    'data' => new StkRecordResource($item)
]);
// 方式2:更新后加载关联
$item->update($request->validated());
$item->load(['vehicle:id,name']);

return response()->json([
    'data' => new StkRecordResource($item)
]);

内容的提问来源于stack exchange,提问作者Jakub Rony Roncak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 07:42:38