Event-Driven Laravel Applications

Event-Driven-Laravel-Applications.jpg

This blog post was written under the Pusher Guest Writer program. In this is post, we’ll be looking at what event-driven programming is and how to get started building event-driven applications in Laravel. We’ll also look at how to decouple various aspects of your application by using event-driven programming. As a heads up, this article \[…\]

Introduction

This blog post was written under the Pusher Guest Writer program.

In this is post, we’ll be looking at what event-driven programming is and how to get started building event-driven applications in Laravel. We’ll also look at how to decouple various aspects of your application by using event-driven programming.

As a heads up, this article assumes you have prior knowledge of Laravel Events and will not cover the basics. You might want to visit Laravel Events if there is a need to catch up.

What are Event Driven Applications?

Before we dive into what Event Driven Applications are, let’s also take a moment to define what Event Driven Programming is. According to Wikipedia_:_

Event-driven programming is a programming paradigm in which the flow of the program is determined by events such as user actions (mouse clicks, key presses), sensor outputs, or messages from other programs/threads. Event-driven programming is the dominant paradigm used in graphical user interfaces and other applications (e.g. JavaScript web applications) that are centered on performing certain actions in response to user input.

Event-driven programming

With the understanding of the definition above, an event-driven application is an application that largely responds to actions generated by the user or the application. The application then executes other code in response to the actions.

What Are Laravel Events?

Simply put, events are actions that occur within an application. Coming from the world of JavaScript, you probably understand events as user actions such as mouse click, mouseover, key press etc. In Laravel, events can be various actions that occur within an application such as email notifications, logging, user sign up, CRUD operations etc. Laravel events provide a simple observer implementation, allowing you to subscribe and listen for various events that occur in your application.

Some of these events are fired automatically by the framework (Laravel) when certain activities occur. For example, when create, save, update or delete operations are performed on an Eloquent model, Laravel will fire created, saved, updated and deleted events respectively. We can hook into these events and perform other activities within our application. In addition to those events which Laravel automatically fires, you can also fire your own custom events to suit your application. For example, you could fire a userRegistered event to send a welcome mail to users that sign up on your application.

Firing an event won’t do anything on its own; we have to listen for the event that has been fired and respond accordingly. Laravel events are comprised of two parts: Event Handler and Event Listener. The Event Handler contains the information associated with the event fired. The Event Listener, on the other hand, simply listens for the event instance and responds to it accordingly. Within the Listener is where we’ll implement the event implementation logic. Event classes are typically stored in the app/Events directory, while their listeners are stored in app/Listeners.

Why Event-Driven Laravel Applications?

So you have seen what event-driven applications and Laravel events are, and you are wondering why you should build your application using this event-driven approach. Well, let’s take a look at some of its benefits.

Firstly, events serve as a great way to decouple various aspects of your application, since a single event can have multiple listeners that do not depend on each other. By decoupling, you don’t pollute your code base with code that doesn’t necessarily fit the domain logic. Secondly, because your application is loosely coupled, you can easily extend the functionality of the application without breaking/rewriting the application or at least some other functionalities of the application.

Practical Implementation

Can we see some code ?. Imagine we have an application that we want to send welcome emails to newly signed up users and at the same time sign them up for weekly newsletters. Normally, we might have something similar to the snippet below to accomplish that:

1// without event-driven approach
2
3    public function register(Request $request)
4    {
5        // validate input
6        $this->validate($request->all(), [
7          'name' => 'required',
8          'email' => 'required|unique:users',
9          'password' => 'required|min:6|confirmed',
10        ]);
11
12        // create user and persist in database
13        $user = $this->create($request->all());
14
15        // send welcome email
16        Mail::to($user)->send(new WelcomeToSiteName($user));
17
18        // Sign user up for weekly newsletter
19        Newsletter::subscribe($user->email, [
20          'FNAME': $user->fname,
21          'LNAME': $user->lname
22        ], 'SiteName Weekly');
23
24        // login newly registered user
25        $this->guard()->login($user);
26
27        return redirect('/home');
28    }

As you can see, the send welcome mail and newsletter signup are tightly coupled to the register method. According the principle of separation of concerns, is the register method supposed to be concerned with the actual implementations of sending welcome email or even newsletter signup? Though you might be thinking, well it just sending mail and newsletter signup which are quite small and it’s fine in the register method. What if in addition to sending mail, you want to also send SMS? You might end up with something like below:

1// without event-driven approach
2
3    public function register(Request $request)
4    {
5        // validate input
6
7        // create user and persist in database
8
9        // send welcome email
10        Mail::to($user)->send(new WelcomeToSiteName($user));
11
12        // send SMS
13        Nexmo::message()->send([
14          'to' => $user->phone_number,
15          'from' => 'SiteName',
16          'text' => 'Welcome and thanks for signup on SiteName.'
17        ]);
18
19        // Sign user up for weekly newsletter
20        Newsletter::subscribe($user->email, [
21          'FNAME': $user->fname,
22          'LNAME': $user->lname
23        ], 'SiteName Weekly');
24
25        // login newly registered user
26
27        return redirect('/home');
28    }

You can see how easily the code base begins to be bloated. But how can we resolve this? Event driven programming to the rescue! So let’s see what the code will look like using this approach to achieve the same functionality as above.

1// with event-driven approach
2
3    public function register(Request $request)
4    {
5        // validate input
6        $this->validate($request->all(), [
7          'name' => 'required',
8          'email' => 'required|unique:users',
9          'password' => 'required|min:6|confirmed',
10        ]);
11
12        // create user and persist in database
13        $user = $this->create($request->all());
14
15        // fire event once user has been created
16        event(new UserRegistered($user));
17
18        // login newly registered user
19        $this->guard()->login($user);
20
21        return redirect('/home');
22    }

Now once a user is created, the UserRegistered event will be fired. Recall that we mentioned earlier that firing an event won’t do anything on its own; we need to listen for the UserRegistered event and carry out necessary actions. Let’s create the UserRegistered event and the SendWelcomeMail and SignupForWeeklyNewsletter listeners to start with:

1artisan make:event UserRegistered
2    artisan make:listener SendWelcomeMail --event=UserRegistered
3    artisan make:listener SignupForWeeklyNewsletter --event=UserRegistered

Open app/Events/UserRegistered.php and update the constructor as below:

1// app/Events/UserRegistered.php
2
3    public $user;
4
5    public function __construct(User $user)
6    {
7      $this->user = $user;
8    }

By declaring the $user variable public, it will be passed to the listeners and the listeners can in turn do whatever that’s necessary with it. Next, the event listeners will receive the event instance in their handle method. Within the handle method, we can perform any actions necessary to respond to the event:

1// app/Listeners/SendWelcomeMail.php
2
3    public function handle(UserRegistered $event)
4    {
5      // send welcome email
6      Mail::to($event->user)->send(new WelcomeToSiteName($event->user));
7    }
8
9
10    // app/Listeners/SignupForWeeklyNewsletter.php
11
12    public function handle(UserRegistered $event)
13    {
14      // Sign user up for weekly newsletter
15      Newsletter::subscribe($event->user->email, [
16        'FNAME': $event->user->fname,
17        'LNAME': $event->user->lname
18      ], 'SiteName Weekly');
19    }

You can see how we have been able to get loosely coupled code and so kept our register method code as minimal as possible. Now let’s say we want to send SMS to newly registered users. All we have to do is create a new event listener to listen for when UserRegistered event is fired:

1artisan make:listener SendWelcomeSMS --event=UserRegistered

And place the SMS sending implementation within the handle method of SendWelcomeSMS:

1// app/Listeners/SendWelcomeSMS.php
2
3    public function handle(UserRegistered $event)
4    {
5      // send SMS
6      Nexmo::message()->send([
7        'to' => $event->user->phone_number,
8        'from' => 'SiteName',
9        'text' => 'Welcome and thanks for signup on SiteName.'
10      ]);
11    }

That’s all. Notice that there was no need to alter or add anything to the register method.

Conclusion

In this post we have been able to understand what event driven programming is, what event driven applications are and what Laravel events are. We also looked at possible advantages of event driven applications. But like pretty much every programming concept that has positive effects, it also tends to have downsides. The major downside to event-driven applications is that it can be hard to really understand the flow of the application. Take our implementation above for example, someone (say a new developer) going through the register method might not know we are sending a welcome mail to the new user and also signing them to a newsletter.

So I would say you use event driven-approach in your Laravel applications as creative as possible and not over do it. Generally, I think event-driven Laravel applications are cool ?. What do you think? Let’s have your thought in the comment below.