У меня есть модель имеет атрибут, который приведен к массиву, например, так
protected $casts = [
'data' => 'array',
];
Мне нужно внести поправку в массив перед возвратом коллекции. С использованием each
Метод на коллекции я могу внести изменения в атрибуты внутри.
$collection = $collection->each(function ($collection, $key) {
if ($collection->type == 'foo') {
$collection->type = 'bar';
}
});
Это работает, и коллекция изменена. Однако мне нужно изменить массив в атрибуте cast.
$collection = $collection->each(function ($collection, $key) {
if ($collection->type == 'foo') {
foreach ($collection->data['x'] as $k => $v) {
$collection->data['x'][$k]['string'] = 'example';
}
}
});
Однако это возвращает ошибку.
Indirect modification of overloaded property App\Models\Block::$data has no effect
Я понимаю, что доступ к данным $ collection-> будет использовать магию __получить() используется, поэтому мне нужно будет использовать сеттер. Так как мне этого добиться?
Заранее спасибо.
Предположительно, вы можете взять весь массив, выполнить ваши изменения и затем установить его:
$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);
}
}
Других решений пока нет …