Easiest way to bind events to your models

profile picture

Easiest way to bind events to your models

In this article I'll explain what I think is the easiest and cleanest way to bind events to your models in Laravel 5.

In fact, I am working on a new project right now and I needed to implement a notification feature to the platform. I was thinking "what's the best way to do that ?".

Basically you would include some lines of code in your controller, like $notification = new Notification; in the store method, in order to create a notification when something is created in your database.

Well another cool solution is Laravel's Events feature. It basically allows you to trigger some functions when something is happening on your application.

Something like :

  • A user like the post of another user.
  • This action triggers a new notification.
  • This action also triggers a new email notification.
  • This action would also trigger something else, increment a variable or something

Of course you don't want to put all these in your controller, otherwise it's becoming kinda messy...

Thus, let's talk about Laravel's Events.

First thing first, you need to open the app/Providers/EventServiceProvider.php file.

You already have a $listen array, that provides an example:

protected $listen = [
    'event.name' => [
        'EventListener',
    ],
];

Now let's use some real example to really understand how it works:

protected $listen = [
    'App\Events\PostWasLiked' => [
        'App\Handlers\Events\EmailThePostAuthorThatHisPostWasLiked',
        'App\Handlers\Events\NotifyThePostAuthorThatHisPostWasLiked',
    ],
    'App\Events\PostWasCommented' => [
        'App\Handlers\Events\EmailThePostAuthorThatHisPostWasCommented',
        'App\Handlers\Events\NotifyThePostAuthorThatHisPostWasCommented',
        'App\Handlers\Events\NotifyTheUsersThatHasCommentedBeforeThatThePostWasCommented',
    ],
];

In this array, you basically create a list of all the events you want to trigger after a certain event. The keys in the array are the event itself (Post Was Liked) and the values are the actions that are going to be triggered.

Yes, these are all php Classes, and they don't exist yet. Our first step was to establish a list of all events and actions that we want in our application. Here for example, when a post is liked, I want to send an email to the author, but also to create an in-app notification (facebook like). And when a post is commented, I'm doing the same thing, but also notify the other users that have already commented this post (exactly like facebook does).

As you see, I like to name my Classes in understandable words, so you instantly get what is going on.

No more being lost in your code :)

Alright, step 2 !

Cool, we have listed all our events and actions. Now it's time to make them real. And when I mean real, I mean to generate the files in which we are going to include our lines of code, to actually create notification and send emails, etc.

Fortunately, Laravel's Artisan command allows you to generate all those files with one little command line ! Let's try it out :

php artisan event:generate

You should now see a bunch of new files in app/Events (your events), and in app/Handlers/Events (your actions that will be triggered).

Cool ! We have almost all we need !

But we still need to actually fire these Classes methods, and to pass datas to them.

Here comes the model binding

Instead of triggering yourself a function in your controller, you surely want to listen to your model and do something when, for example, your "Post" model creates a new entry in the database. That's what the boot method of the EventServiceProvider will do for you.

Let's see an actual example :

public function boot(DispatcherContract $events)
{
    parent::boot($events);

    Like::created(function($like) {
        event(new PostWasLiked($like));
    });
    Comment::created(function($comment) {
        event(new PostWasCommented($comment));
    });
}

Here we use Model's listeners to fire the events. So when a Like (model) is created with the save() method, it will fire the "PostWasLiked" event, and the trigger all our listed actions.

You can learn more about this here.

The $like and $comment variable are the actual data that was just stored in the database. So we grab them and pass them to our event Class.

#It's now time to pass the data to the final action's method where we will put our code.

Inside your events Classes, you need to pass the data to the constructor, like this :

// app/Events/PostWasLiked.php
class PostWasLiked extends Event {
    use SerializesModels;

    public $like;

    /**
    * Create a new event instance.
    *
    * @return void
    */
    public function __construct($like)
    {
        $this->like = $like;
    }
}

Easy stuff

Final step is to receive the datas in the methods we will put our code into:

// app/Handlers/Events/NotifyThePostAuthorThatHisPostWasLiked.php
class NotifyThePostAuthorThatHisPostWasLiked {
    /**
    * Create the event handler.
    *
    * @return void
    */
    public function __construct()
    {
        //
    }

    /**
    * Handle the event.
    *
    * @param  PostWasLiked  $event
    * @return void
    */
    public function handle(PostWasLiked $event)
    {

        $notif = new Notification;
        $notif->user_id = $event->like['attributes']['user_id'];
        $notif->message = 'Hey ! Someone liked your post :)';
        $notif->save();

        $event->like['attributes']; // This is the array containing the datas from your database. Do whatever you want with it :)
    }
}

We clearly see that your code needs to be place in the handle method and that the $event object contains your datas

Now we have a super clear way to handle events in our application !! yay !

There might be better ways to do all these, and if you have any suggestions, don't hesitate to comment just below :)

about me

profile picture

I consider myself as an IT Business Artisan. Or Consultant CTO. I'm a self-taught Web Developper, coach and teacher. My main work is helping and guiding digital startups.

more about me

follow me

newsletter

A weekly email with the latests articles

support my work

Start trading on binance
  • BTC

    BTC

    18SY81ejLGFuJ9KMWQu5zPrDGuR5rDiauM

  • ETH

    ETH

    0x519e0eaa9bc83018bb306880548b79fc0794cd08

  • Monero

    XMR

    895bSneY4eoZjsr2hN2CAALkUrMExHEV5Pbg8TJb6ejnMLN7js1gLAXQySqbSbfzjWHQpQhQpvFtojbkdZQZmM9qCFz7BXU

2024 © My Dynamic Production SRL All rights Reserved.