Laravel依赖注入实例化模型时附加属性返回空值问题
问题
我定义了一个附加属性,当使用Model::first()->appended_attribute调用时可正常返回值,但通过Laravel路由依赖注入实例化模型对象时,如以下代码:
public function update(UserRequest $request, User $user) { $user->appended_attribute; // 返回null }
访问该属性会返回null,执行$user->toArray()时可见该附加属性存在但值为null。而使用以下代码时:
public function update(UserRequest $request, User $user) { User::find($user->id)->appended_attribute; // 返回正确值 }
则能正常获取正确值。附加属性的定义方法如下:
public function getCurrentRoleAttribute() { return $this->roles->first(); }
请问我忽略了什么细节?
解答
核心原因:路由模型绑定的实例未预加载关联关系
路由依赖注入生成的$user实例,默认只会查询模型自身字段,不会自动加载roles关联。而附加属性current_role依赖$this->roles,此时roles关联属于未触发的延迟加载状态,在路由模型绑定的初始化逻辑中,延迟加载未被正确触发,导致关联数据为空,最终附加属性返回null。
而User::find($user->id)是重新查询并实例化模型,此时访问roles会正常触发延迟加载,获取到关联数据,所以附加属性能返回正确值。解决方法
- 预加载关联关系
给路由模型绑定的实例预加载roles关联,有两种实现方式:- 方式一:在路由定义中指定预加载
Route::put('/users/{user}', [UserController::class, 'update'])->with('roles'); - 方式二:在模型中添加全局作用域自动预加载
在User模型中添加以下代码:protected static function booted() { static::addGlobalScope('withRoles', function ($query) { $query->with('roles'); }); }
- 方式一:在路由定义中指定预加载
- 修改附加属性强制触发关联加载
在附加属性的getter方法中明确调用load方法确保关联被加载:
注意:这种方式每次访问附加属性都会执行一次查询,对性能敏感的场景建议优先使用预加载方案。public function getCurrentRoleAttribute() { return $this->load('roles')->roles->first(); }
- 预加载关联关系
内容的提问来源于stack exchange,提问作者Mohamed DS
相关产品推荐
相关产品推荐

