Eloquent support
JsonShape's main purpose is to make JSON columns first-class on your Eloquent models. This page goes end to end: the migration, the cast, and using the shape.
It uses the TraceShape defined earlier.
1. The migration
Store the data in a json column like any other JSON attribute:
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('examples', function (Blueprint $table) {
$table->id();
$table->json('trace');
$table->timestamps();
});
}
};2. The cast
Point an AsJsonShape cast at your shape. On read, the column's JSON is decoded into a TraceShape; on save, the shape is encoded back to JSON. No accessors, no manual json_decode.
<?php
namespace App\Models;
use App\Shapes\TraceShape;
use Illuminate\Database\Eloquent\Model;
use Plumthedev\JsonShape\Casts\AsJsonShape;
/**
* @property TraceShape $trace
*/
class Example extends Model
{
protected $fillable = ['trace'];
/** @return array<string, mixed> */
public function casts(): array
{
return [
'trace' => AsJsonShape::of(TraceShape::class),
];
}
}TIP
Add the @property TraceShape $trace docblock on the model so your IDE and PHPStan know the attribute's type.
INFO
Need a generic, untyped shape instead of a dedicated class? Cast with AsJsonShape::class and you'll get a plain JsonShape back.
3. Using it
Once cast, the shape is just an attribute on the model — read and mutate it with the accessors from Reading and Setting properties:
$model = Example::find(1);
// read
$model->trace->traceId;
// write — then persist as usual
$model->trace->setContext([
'userId' => 'superSimple',
'levelNumber' => $model->trace->getNonsenseInt(),
]);
$model->save();