Custom Eloquent Model Events

Posted on Updated on Laravel by Gergő D. Nagy

Laravel’s Eloquent offers a bunch of default model events out of the box. However, it also offers the possibility to define and listen to our custom events. Let’s see how!

Firing Custom Events

Model events are providing a good spot to react to the different states of our models. Laravel has a lot of events by default, but we can move a bit forward and add our own, more specific ones. Let’s see an example:

class Message extends Model
{
    /**
     * User exposed observable events.
     *
     * These are extra user-defined events observers may subscribe to.
     *
     * @var array
     */
    protected $observables = [
        'reading',
        'read',
    ];

    /**
     * Read the message.
     *
     * @return void
     */
    public function read()
    {
        $this->fireModelEvent('reading', true);

        $this->update(['read_at' => now()]);

        $this->fireModelEvent('read', true);
    }
}

From now, when we call the $message->read() method on our model instance, it won’t just update the read_at column on our model but will fire the reading and the read events as well.

Listening to Custom Events

We can set up an event listener as it would be a default model event:

use Illuminate\Support\Facades\Event;

Event::listen('eloquent.reading: App\Message', function ($model) {
    // perform action...
});

Adding this code to a service provider – usually the AppServiceProvider – we are ready to listen to our model’s custom events.

Also, you may notice the $observables array. By adding our custom events there, we make those events observable. This means if we register an observer class for our model, we can add the reading and read method to catch events using the observer.

Summary

Mostly, the default events are enough, no need to define custom ones. However, in some cases refactoring some logic to listeners that are subscribed to custom model events can be a good refactoring and separation strategy.

Need a web developer? Maybe we can help, get in touch!