How to Cast Pivot Table Columns in Laravel

January 30th, 2025 • 2 minutes read time

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:

  1. Create a model that represents the pivot table (php artisan make:model NotificationUser --pivot)
  2. Use using on the relationship (->using(NotificationUser::class))
  3. Add $casts to your pivot model

Happy casting!

If you found this article helpful, you'll love our practical screencasts.
Author
Alex Garrett-Smith
Share :

Comments

No comments, yet. Be the first!