I have been using traits extensively in my Eloquent models to segregate related functionalities. For instance, a User model might incorporate the HasRole trait, allowing me to define related query scopes, helper methods to determine current user role, and functions to modify the user role.

When you attach a trait to an Eloquent model, Laravel automatically invoke two related methods that can be utilized to alter the model’s behavior. Assuming we are using the HasRole trait as an example, these two methods will be automatically called:

  • bootHasRole
  • initializeHasRole.

It follows the pattern of boot<TraitName> and initialize<TraitName>, as you can see from the underlying source code.

While boot<TraitName is a static method and cannot be used to modify the $fillable property, initialize<TraitName is not, making it the perfect entry point.

Staying consistent with the same HasRole example, I prefer to push it further by defining all related column inside the trait itself. Assuming the trait requires a column in the users table called role to function, I do as follows:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// app/Traits/HasRole.php
<?php

namespace App\Traits;

use App\Enums\Role;

trait HasRole
{
    protected function initializeHasRole(): void
    {
        $this->fillable[]    = 'role';
        $this->casts['role'] = Role::class;
    }
    
    // all other related methods to the role over here
}

As a bonus point, every property can be modified at this juncture, so I also modify the $casts property to also recognize role as castable to the related enum.