Keep the Code Clean with Laravel Events

In many cases, when our application becomes bigger, and it needs to handle more and more tasks, the size of our controllers, presenters or services can be increased fast, and easily becomes hard to work with, untestable and slow.

Simplicity in charge

Reorganizing our logic, and placing a different kind of tasks to dedicated classes, can be very useful, and it’s a recommended “best” practice.

Why? Working with more but smaller pieces is much easier than handle everything in a huge monolith. At the top of that, your app becomes more testable, you don’t break SRP, and finally you can easily get cleaner and nicer code.

Getting started with events

One of the useful techniques is Laravel’s event service. First of all, in various cases, by moving tasks to the event classes drastically cleans up our controller. Another reason for using events is the queue system, what allows your app to complete jobs asynchronously, which can highly speed up your application.

The event system has two important parts. The event itself, and the listener what can be bound to specific events. The event class is responsible for serializing the incoming data, and pass it to the listener, what is aimed to process the logic after the event was fired.

Using events in real life

Trigger an event has never been easier, all we have to do is to call the event() helper, and give the event’s class as a parameter. In our case: event(UserRegistered::class).

Through a common example, let’s take a look how it works in real life. In our app, we want to send a welcome email to our fresh users.

First, we need to bind the events and listeners in our EventServiceProvider.  We can attach more listeners to an event if we want to handle different logics on a specific event.

// app/Providers/EventServiceProvider.php

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Event;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;

class EventServiceProvider extends ServiceProvider
{
    protected $listen = [
        'App\Events\UserRegistered' => [
            'App\Listeners\SendWelcomeEmail',
        ],
    ];
}

When the bindings are ready, we can generate our event – listener pairs with the PHP artisan event:generate command, or we can create them individually with the artisan make commands.

Our event has not other responsibility but assigns the user as a public property, which may pass to the listener.

// app/Events/UserRegistered.php

<?php

namespace App\Events;

use App\User;

class UserRegistered
{
    public $user;

    public function __construct(User $user)
    {
        $this->user = $user;
    }
}

Our listener does the important part. It implements the ShouldQueue interface, which means this event is going to be pushed to the queue stack. In the handle method, we are implementing the logic what takes care of sending the email to the given user.

// app/Listeners/SendWelcomeEmail.php

<?php

namespace App\Listeners;

use App\Mail\WelcomeEmail;
use App\Events\User\Created;
use Illuminate\Support\Facades\Mail;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;

class SendWelcomeEmail implements ShouldQueue
{
    use InteractsWithQueue;

    public function handle(Created $event)
    {
         Mail::to($event->user)->send(new WelcomeEmail($event->user));
    }
}

Reorganizing our logic can be very useful, especially when you need to take care of a lot of tasks. Events and listeners may be a good help for you. You can find the official Laravel events documentation here.