背景: laravel原来可以把数据库中的JSON / TEXT
字段转换为array
或collection
,类似这样:
$casts = ['options' => 'array'];
但是这个特性,带来很多便利的同时,也有一些不足之处,比如当只是更新array当中某个属性时,很多开发者倾向于这样写:
$user = User::find(1);
$user->options['foo'] = 'bar';
$user->save();
貌似应该起作用的逻辑,在这里却不行,这个经过laravel cast转换出来的array,要更改其中的某个属性,必须对整个array进行操作才行,通常是覆写整个array:
$user = User::find(1);
$user->options = ['foo' => 'bar'];
$user->save();
为了解决这个可能误导很多新手的问题,在laravel 8的后期版本,开始引入了AsArrayObject + AsCollection这两个新的cast类型。AsArrayObject通过PHP的ArrayObject来实现,能够以array的常见方式来操作object:
// model里定义cast...
$casts = ['options' => AsArrayObject::class];
// 具体操作...
$user = User::find(1);
$user->options['foo']['bar'] = 'baz';
$user->save();
需要注意的是,这个时候的ArrayObject ,不能放进常见的array函数里来操作,比如array_map, 这种情况下,你可以通过$user->options->toArray()
来获取其背后的原始array,或者也可以通过$user->options->collect()
来将其转换为collection实例。
基于其新增的便利,所以以后我们再想着cast某个字段为array或者collection的时候,不妨默认cast为AsArrayObject或者AsCollection类型,以后的laravel文档也会重点展示这两个类型的使用。