Laravel Eloquent中如何在__construct构造函数中获取模型属性?
能不能在Laravel Eloquent模型的构造函数中访问属性?
首先直接给结论:分情况——手动传入的属性可以,从数据库查询出来的属性不行,这也是你当前代码返回null的核心原因,下面详细拆解:
为什么你的代码返回null?
先看你写的构造函数代码:
public function __construct() { parent::__construct(); dd($this->attributes); }
有两个场景会导致$this->attributes为空:
- 如果你是手动实例化模型且不传属性(比如
new YourModel()):父类构造接收的$attributes是空数组,执行fill($attributes)后自然没有任何属性值,所以$this->attributes是空的。 - 如果你是从数据库查询模型(比如
YourModel::find(1)):Eloquent的实例化流程是先调用构造函数创建模型对象,之后才会把数据库查询到的属性填充到模型里。所以构造函数执行时,数据库的属性还没被赋值,$this->attributes自然是空的。
什么时候能在构造函数里访问属性?
只有当你手动给构造函数传入属性数组的时候,比如:
$model = new YourModel(['name' => 'Laravel', 'status' => 1]);
这时候在你的构造函数里调用dd($this->attributes),就能看到传入的name和status属性了——因为父类构造的fill($attributes)已经把这些值填充到$this->attributes里了。
要访问数据库加载的属性?用这些替代方案
如果你的需求是在模型从数据库加载完成后立即处理属性,别用构造函数,试试下面的方法:
方案1:使用retrieved模型事件
在你的模型里定义booted方法,注册retrieved事件——这个事件会在模型从数据库查询出来后触发,此时所有数据库属性都已填充完成:
protected static function booted() { static::retrieved(function ($model) { // 这里可以正常访问所有数据库加载的属性 dd($model->attributes); // 也可以直接用属性访问器,比如$model->name }); }
方案2:使用initialize方法(适合Trait场景)
如果你的模型使用了自定义Trait,或者想在模型初始化的后期执行逻辑,可以定义initialize方法(注意:这个方法依然早于数据库属性填充,所以如果是查询模型的话,还是优先推荐retrieved事件):
public function initialize() { // 这里可以处理手动传入的属性,数据库属性依然拿不到 if (isset($this->attributes['name'])) { // 写你的处理逻辑 } }
总结一下:构造函数只适合处理手动传入的初始化属性,数据库加载的属性需要用模型事件来处理。
内容的提问来源于stack exchange,提问作者Andreas Hunter
相关产品推荐
相关产品推荐

