laravel-versionable
laravel-versionable copied to clipboard
Revert applies casted data to raw attributes array
Similar to #84, but basically I found that using setRawAttributes() is just not desired at all. When a model that has been reverted needs to be serialized (e.g. in an API response) it fails because the raw attributes array may contain data in a format that Eloquent doesn't expect.
You need some mechanism to convert the cast data back into its raw type if you're going to use setRawAttributes().
So I found it's better to simply attempt to set the values on the model directly e.g.:
foreach ($this->contents as $key => $value) {
$this->versionable->$key = $value;
}
I noticed you were using forceFill at one point, which feels like it's the right approach, but I'm not clear why this needed to change.
maybe you can refresh() after revert the model.
No I can't as I'm using revertWithoutSave() directly as I only want to 'revert' to the version for the life of the request. So I'm not persisting the revert to the DB.
But part of that request requires the model to be serialised, and this fails because of the casted attributes living in the raw attributes.
It's just completely the wrong state for the model to be in.
can you paste an example data ?
Model with an array cast:
<?php
namespace App\Models;
use Illuminate\Eloquent\Model;
class Test extends Model
{
protected $casts = [
'column' => 'array',
];
}
$model = Test::make([
'column' => ['foo' => 'bar'],
]);
dd($model);
// 'attributes' => ['column' => '{"foo": "bar"}']
Note how Eloquent has serialised the data into the model attribute on entry, not on save. Eloquent and other systems (in my case, Inertia) rely on this internal state being a string.
However, your implementation using setRawAttributes() will have this value appear as:
// 'attributes' => ['column' => ['foo' => 'bar']]
Hence the error I'm seeing