Listening for Model Events in Laravel can sometimes be a tedious task. It usually becomes quite unmanageable to maintain when a client or application requires additional features. In this post I'll be explaining how we currently handle our model events in our applications and how you can clean up your controllers.
Note: I'm going to go ahead and assume you're comfortable with Laravel Resource Controllers and the Laravel framework in general
Let say for example we have a Post model and a generic resource controller with a Store method as follows:
Ok, so there's a lot going on here (validation aside), we're taking a post with some text and title, we're logging that it was created for our Log and also sending an email not only to the author that their post was published, we're also notifying some subscribers of that user that a post has been published.
That's a lot of information, and a lot of responsibility for that one method to be having. What if we could just fire an event and let our listeners handle that?
php artisan make:event PostCreatedin your terminal.
This will create a
PostCreated class in your
Events directory inside the app folder.
What we need to do now is make sure that the event has access to the model we will need to listen for. So what you'll need to do is something like the following:
php artisan create:listener PostEventListener
You'll now see a
PostEventListener class in your
Listeners directory in the app directory.
This time round we're going to go ahead and do something a little different. Although the 'Laravel' way is to handle an event, we've already fired it, so maybe we can do something nice here where we hear an event being created and hook into that to fire off any notifications we might need to handle.
Laravel has a nice way of letting us create our own listener implementations by using the
EventServiceProvider and in our $subscribe array we define what class should be auto-loaded to be able to listen for classes being created. so go ahead and add our new Listener class
App\Listeners\PostEventListener::class to that array.
Now that that's completed we can go ahead and write up our
PostEventListener like follows
By doing this we have been able to negotiate the responsibilities of the
PostController and simply use the method like so:
This feels a lot cleaner now, it also means you can new up a
PostCreated event anywhere in your app and you can guarantee the appropriate notifications etc will be fired.
To take it one step further you could abstract this entire process to a repository class, which can be called from anywhere in your app to store the Post.
That's the basics of making simple and scalable model events and listeners in Laravel. If you're looking for something a little different you can always use Laravel Observers in your models, which are similar except will always fire and sometimes that might not always be appropriate!