novius/laravel-json-casted
Cast JSON columns in Laravel models with per-key casting. Define sub-key casts via a method or dedicated cast class; values are exposed as a Fluent object with proper types (e.g., Carbon dates). Supports PHP 8.2+ and Laravel 10+.
Install via Composer:
composer require novius/laravel-json-casted
For IDE autocompletion (optional but recommended):
// config/laravel-ide-helper.php
'model_hooks' => [
\Novius\LaravelJsonCasted\Hooks\ModelHasJsonWithCastsHook::class,
],
First Use Case: Cast a JSON field with nested sub-keys in an Eloquent model:
// In your model
protected $casts = [
'metadata' => \Novius\LaravelJsonCasted\Services\JsonCasted::class.':getMetadataCasts',
];
public function getMetadataCasts(): array
{
return [
'published_at' => 'date:Y-m-d',
'is_active' => 'boolean',
];
}
// Usage
$post = Post::first();
$post->metadata->published_at; // Now a Carbon instance
$post->metadata->is_active; // Now a boolean
// Model: Post.php
protected $casts = [
'settings' => JsonCasted::class.':getSettingsCasts',
];
public function getSettingsCasts(): array
{
return [
'theme' => 'string',
'notifications' => 'array',
'last_login' => 'datetime',
];
}
Workflow:
get{FieldName}Casts).date:Y-m-d, boolean).$model->settings->last_login).// Cast: SettingsCast.php
namespace App\Casts;
use Novius\LaravelJsonCasted\Services\JsonCasted;
class SettingsCast extends JsonCasted
{
protected static array $casts = [
'theme' => 'string',
'notifications' => 'array',
'last_login' => 'datetime',
];
}
// Model: Post.php
protected $casts = [
'settings' => \App\Casts\SettingsCast::class,
];
Workflow:
JsonCasted to add custom casting logic if needed.// API Resource: PostResource.php
public function toArray($request)
{
return [
'id' => $this->resource->id,
'title' => $this->resource->title,
'settings' => $this->resource->settings, // Automatically casted
];
}
Tip: The package works seamlessly with Laravel’s API resources. No additional configuration is needed.
// Model: Post.php
protected $casts = [
'dynamic_data' => JsonCasted::class.':getDynamicCasts',
];
public function getDynamicCasts(): array
{
$casts = [];
if ($this->type === 'premium') {
$casts['expiry_date'] = 'datetime';
}
return $casts;
}
Use Case: Dynamically define casts based on model attributes or business logic.
Fluent Syntax Conflicts:
$model->extras['date']), the fluent syntax ($model->extras->date) will fail.Circular References:
try {
$model->extras->nested_field;
} catch (\Exception $e) {
// Fallback to raw JSON
$model->extras = json_decode($model->extras, true);
}
Database-Level Casting:
jsonb), the package may apply casting twice, leading to unexpected behavior.AGPL License:
Check Casted Values:
dd($model->extras) to inspect the casted structure. If values are not casted as expected, verify the $casts array in your model or cast class.Validate JSON:
if (json_validate($model->extras)) {
$model->extras = json_decode($model->extras);
}
Override Default Casting:
JsonCasted class to customize behavior:
class CustomJsonCasted extends JsonCasted
{
public function castUsing(array $casts, $value)
{
// Custom logic here
return parent::castUsing($casts, $value);
}
}
Performance Monitoring:
// Benchmark casting
$start = microtime(true);
$model->extras->nested_field;
$time = microtime(true) - $start;
Custom Casts:
class CustomCast implements \Illuminate\Contracts\Database\Eloquent\CastsAttributes
{
public function get($model, string $key, $value, array $attributes)
{
// Custom casting logic
return $value;
}
public function set($model, string $key, $value, array $attributes)
{
// Custom setting logic
return $value;
}
}
$casts array.Global Casting:
// AppServiceProvider.php
Model::resolveCast('json_casted', function () {
return \Novius\LaravelJsonCasted\Services\JsonCasted::class;
});
Fallback to Raw JSON:
public function getExtrasCasts(): array
{
return [
'date' => 'date:Y-m-d',
// Fallback to raw value if casting fails
'fallback' => function ($value) {
return $value ?? null;
},
];
}
IDE Helper Configuration:
// config/laravel-ide-helper.php
'model_hooks' => [
\Novius\LaravelJsonCasted\Hooks\ModelHasJsonWithCastsHook::class,
// Add other hooks as needed
],
How can I help you explore Laravel packages today?