如何在Laravel Eloquent模型中实现数据加载后的恢复逻辑?
解决Laravel 5.6 Eloquent模型加载后执行代码的问题
针对你说的从数据库加载模型时需要恢复JSON存储的复杂属性的场景,有几个靠谱的方案,我一个个给你拆解:
方案一:利用Eloquent的retrieved事件
这是最贴合需求的方式,因为retrieved事件就是专门在模型从数据库检索出来后触发的。你可以在模型的booted方法里注册这个事件的处理逻辑:
namespace App; use Illuminate\Database\Eloquent\Model; class YourModel extends Model { // 假设存储JSON的数据库字段叫complex_attributes protected $fillable = ['complex_attributes']; protected static function booted() { static::retrieved(function ($model) { // 在这里编写你需要执行的代码,比如把JSON转成复杂属性 $model->complex_properties = json_decode($model->complex_attributes, true); // 如果需要转成自定义类实例,也可以在这里处理 // $model->complex_properties = new YourCustomComplexClass(json_decode($model->complex_attributes, true)); }); } }
这样每次从数据库查询出该模型的实例时,retrieved闭包里的代码都会自动执行,帮你完成复杂属性的恢复。
方案二:使用访问器(Accessor)
如果你的复杂属性是和某个数据库字段绑定的,访问器会更优雅——它会在你访问模型属性时自动完成转换:
namespace App; use Illuminate\Database\Eloquent\Model; class YourModel extends Model { protected $fillable = ['complex_attributes']; // 定义访问器,对应属性名采用驼峰命名(complexProperties) public function getComplexPropertiesAttribute() { // 从数据库字段读取并转换 $rawData = json_decode($this->attributes['complex_attributes'], true); // 这里可以做复杂的自定义处理,比如实例化专属类 return new YourCustomComplexClass($rawData); } // 搭配修改器(Mutator),保存时自动把复杂属性转成JSON public function setComplexPropertiesAttribute($value) { $this->attributes['complex_attributes'] = json_encode($value->toArray()); } }
之后你在代码里直接用$model->complexProperties就能拿到处理后的复杂属性,保存时直接赋值$model->complexProperties = $yourComplexObject,修改器会自动帮你转成JSON存入数据库,完全不用手动处理转换逻辑。
方案三:结合$casts属性(适合简单复杂结构)
如果你的复杂属性只是普通数组或标准对象,不需要自定义类,那直接用$casts属性最省事:
namespace App; use Illuminate\Database\Eloquent\Model; class YourModel extends Model { protected $fillable = ['complex_attributes']; // 自动把数据库的JSON字符串转成数组,保存时自动转回JSON protected $casts = [ 'complex_attributes' => 'array', // 如果需要转成标准对象,就改成'object' // 'complex_attributes' => 'object', ]; }
不过如果是需要自定义的复杂类实例,这个方案就满足不了需求了,还是得用前两个方案。
为什么fill()不行?
你说的完全没错,fill()方法只会在批量赋值或者手动调用时触发,而从数据库查询模型实例时,Laravel是直接从查询结果构建模型,不会走fill()的流程,所以用它处理加载逻辑确实行不通。
内容的提问来源于stack exchange,提问作者AsTeR
相关产品推荐
相关产品推荐

