修改 Laravel 中的 collection 中的 cast 属性

Amending a cast attribute inside a collection in Laravel

我有一个模型有一个被转换为数组的属性,就像这样

protected $casts = [
   'data' => 'array',
];

我需要在返回 Collection 之前对数组进行修改。在 Collection 上使用 each 方法我可以更改里面的属性。

$collection = $collection->each(function ($collection, $key) {
    if ($collection->type == 'foo') {
       $collection->type = 'bar';
    }
});

这有效并且 Collection 被改变了。但是我需要更改 cast 属性中的数组。

$collection = $collection->each(function ($collection, $key) {
    if ($collection->type == 'foo') {

        foreach ($collection->data['x'] as $k => $v) {
            $collection->data['x'][$k]['string'] = 'example';
        }

    }
});

然而这returns一个错误。

Indirect modification of overloaded property App\Models\Block::$data has no effect

我知道访问 $collection->data 将使用魔法 __get() 正在被使用,所以我需要使用一个setter。那么我该如何实现呢?

提前致谢。

大概你可以获取整个数组,执行你的修改然后设置它:

$collection = $collection->each(function ($collectionItem, $key) {
    if ($collectionItem->type == 'foo') {
        $data = $collectionItem->data;
        foreach ($data['x'] as $k => $v) {
            $data['x'][$k]['string'] = 'example';
        }
        $collectionItem->data = $data;

    }
});

尽管如果模型的所有用途都需要进行此修改,也许最好在模型自身中进行此修改:

class SomeModel
{


    //protected $casts = [
    //   'data' => 'array',
    //];

    public function getDataAttribute($value)
    {
        $data = json_decode($value);
        foreach ($data['x'] as $k => $v) {
                $data['x'][$k]['string'] = 'example';
        }
        return $data;
    }

    public function setDataAttribute($value)
    {
        $this->attributes['data'] = json_encode($value);
    }

}