composer require raveren/eloquent-data-objectStore PHP objects in Eloquent columns.
Your model column is now a strictly typed object!
Plus, all and any changes to your data classes in the future don't invalidate stored data!
Just extend EloquentDataObject (or see below):
<?php
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Raveren\EloquentDataObject\EloquentDataObject;
Schema::table('my_table', function (Blueprint $table) {
$table->json('json_data')->nullable(); // <---- Step 1/3 -------
});
class MyModel extends Model
{
protected function casts(): array
{
return [
'json_data' => MyData::class // <---- Step 2/3 -------
];
}
}
class MyData extends EloquentDataObject // <---- Step 3/3 -------
{
public string $name;
/** @var MyData[] */
public array $children;
}Objects are stored as JSON inside database.
In PHP however, $myModel->json_data is always an instance of MyData.
Thus, if you receive an associative-array representation, you must convert it to MyData before saving:
$myModel->json_data = MyData::from($array); // helper method comes in the boxIf your data class changes or is renamed, no data is lost and you get no errors¹: if you rename a class attribute, existing data will be preserved as a Dynamic property with the old name.
¹ Newly missing columns in class definitions issue Log::error() with detailed information.
To fix drifted names, define a renamedDataObjectColumns():
class MyData extends EloquentDataObject
{
public string $newName;
public static function renamedDataObjectColumns(): array
{
return [
'name' => 'newName',
'children' => null, // Set new name to null to drop the value from storage on saving.
];
}
}It's enough to load each model once and re-save it to fix the name inside the DB permanently, so you don't have to keep the overridden method if you do that.
- Add
use EloquentDataObjectTrait; - Add
implements Castable - Annotate with
#[AllowDynamicProperties](only if you renamed class attributes)
#[AllowDynamicProperties]
class MyData implements Castable
{
use EloquentDataObjectTrait;
// ...
}Hierarchical object conversion is handled by netresearch/jsonmapper (sole project dependency).
