In this article, I'll show you how to set up casts for pivot table columns in your Laravel relationships.
Adding casts to models by default isn't that tricky. If you're unaware, here's an example of casting a channels
column on a model to json
:
class User extends Authenticatable
{
protected $casts = [
'channels' => 'json'
];
}
This will cast the data in the database (stored as JSON) and decode it. If the data in the database looks like this:
["mail", "slack"]
We'll end up with this (an actual array
, rather than a string
) now that we've cast it:
array:2 [
0 => "mail"
1 => "slack"
]
Once you've understood how to cast regular model columns, casting pivot columns isn't that much different.
Assume we have the following relationship in our User
model:
class User extends Authenticatable
{
// ...
public function notificationPreferences()
{
return $this->belongsToMany(Notification::class)
->withTimestamps()
->withPivot('channels');
}
}
Here's the migration for the notifications_user
table, with the channels
column set to JSON:
Schema::create('notification_user', function (Blueprint $table) {
$table->id();
$table->foreignId('notification_id');
$table->foreignId('user_id');
$table->json('channels');
$table->timestamps();
});
channels
here is what we want to cast. But we can't just add this to the User
model. Instead, we need to create a model that represents the pivot table. We can then add the cast there!
Here's how:
php artisan make:model NotificationUser --pivot
This creates a NotificationUser
model, which extends Pivot
instead:
class NotificationUser extends Pivot
{
}
Now we have this, we can tell the notificationPreferences
relationship to use this model to represent the pivot table:
class User extends Authenticatable
{
// ...
public function notificationPreferences()
{
return $this->belongsToMany(Notification::class)
->withTimestamps()
->withPivot('channels')
->using(NotificationUser::class);
}
}
Now that's added, we can add our $casts
directly to the new pivot model!
class NotificationUser extends Pivot
{
protected $casts = [
'channels' => 'array'
];
}
And now, when we access (in this case) notification preferences for our user, channels
will be represented as an array in PHP (and stored as JSON when inserting).
$user->notificationPreferences->first()->pivot->channels; // This is now a PHP array!
So, in summary, to cast pivot table columns in Laravel:
php artisan make:model NotificationUser --pivot
)using
on the relationship (->using(NotificationUser::class)
)$casts
to your pivot modelHappy casting!