I have a model has an attribute which is cast to an array, like so
protected $casts = [
'data' => 'array',
];
I need to make an amendment to the array before returning the Collection. Using the each
method on the Collection I can make changes to the attributes inside.
$collection = $collection->each(function ($collection, $key) {
if ($collection->type == 'foo') {
$collection->type = 'bar';
}
});
This works and the Collection is altered. However I need to change the array in the cast attribute.
$collection = $collection->each(function ($collection, $key) {
if ($collection->type == 'foo') {
foreach ($collection->data['x'] as $k => $v) {
$collection->data['x'][$k]['string'] = 'example';
}
}
});
However this returns an error.
Indirect modification of overloaded property App\Models\Block::$data has no effect
I understand that accessing $collection->data will be using a magic __get() is being used, so I would need to use a setter. So how do I achieve this?
Thanks in advance.
Presumably you can take the whole array, perform your modifications and then set it:
$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;
}
});
Though if this modification is required for all uses of the model, perhaps it would be better to do this in the model its self:
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);
}
}