背景: laravel原来可以把数据库中的JSON / TEXT字段转换为arraycollection,类似这样:

$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文档也会重点展示这两个类型的使用。

最后修改:2023 年 04 月 07 日
如果觉得我的文章对你有用,请随意赞赏