Hello, today I want to talk about Events and Listeners in Laravel, in programming to write a scalable, reusable and clean code, you need to follow some programming principles, one of which is SOLID, I will not be going deep into explaining that today, but I will just highlight one, the S which stands for Single Responsibility Principle, this principle states that
A class should have one and only one reason to change, meaning that a class should have only one job.
What this means is that, A class should only perform one task, many times, we always load our class with some many functionalities, so if the class changes, a lot of things will break in our application, which is not a good practice.
So I will introduce Events and Listeners to help in making our class perform just one task.
Click on my profile to follow me and get more updates.
What is An Event?
Events are the ways we hook into the activities of our application, it is just a way to observe an activity, for instance, login, a class can be created to monitor the activity of login, when a user logs in, the event class can execute some functions.
What is A Listener?
A Listener is a class that listens to the events that they are mapped to and execute a task, that is they are the ones that perform a given task for an event.
Let me illustrate, you might want to send a welcome email to a new user of your application, and also assign a role to the user based on the information provided in the registration, etc, you would not want to do all those in the RegisterController because that we violate the first principle of SOLID, where the Controller will perform more than one task, the RegisterController needs to only perform the activity of registration of a new user. so an event needs to be carried out in the process of registration, where assigning a role, sending an email, etc are the individual listeners under the event.
For this article, I will write one listener in an event, what the listener will do is to store the login of each user of the app in a table, this is just an illustration that will show you how it works.
If you have a laravel project that has auth already, you can follow immediately, or you can follow my article Basic Laravel Login and Registration using Laravel Breeze, I will be using the project on that article from my system.
Step 1: Register the event and listeners in the EventServiceProvider
For our events and listeners to work, we must register them in the EventServiceProvider class that has already been set up for us at the time of installing our laravel project. So go to app/Providers/EventServiceProvider.php and click
Events and Listeners are registered as key => value pair in the protected $listen, from the picture above, an event and a listener is already registered Registered::class is the event, while SendEmailVerificationNotification::class is the listener, so we are going to add our own
<?php
namespace App\Providers;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;
use App\Events\LoginHistory;
use App\Listeners\storeUserLoginHistory;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
LoginHistory::class => [
StoreUserLoginHistory::class,
]
];
/**
* Register any events for your application.
*
* @return void
*/
public function boot()
{
//
}
}
We added another event class called LoginHistory and also a listener called StoreUserLoginHistory, and noticed up that we called the class here in this way use App\Events\LoginHistory; and use App\Listeners\storeUserLoginHistory;, don't worry, I know you are wondering that the class does not exist in our application, we are going to generate it in the next step, you can add as many events and listeners as possible like this and even more
protected $listen = [
Event1::class => [
Listener1::class,
Listener2::class
],
Event2::class => [
Listener5::class,
Listener7::class
],
Event3::class => [
Listener4::class,
Listener7::class,
Listener9::class
],
];
Step 2: Generate Events & Listeners
Previously, we write classes of events and listeners in the EventServiceProvider, so to generate it at once, we run this command
php artisan event:generate
That command will automatically generate all the events and listeners found in the event provider,
Step 3: Write the Events and Listener class
Remember what we are trying to achieve was to store all the login of our app in a table, so click on the app/Events/LoginHistory.php and edit as follows
class LoginHistory
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $user;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct($user)
{
$this->user = $user;
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}
from the code above, the event accepts the $user which is the information of the user, and it will pass it to the listener.
Click on app/Listeners/storeUserLoginHistory.php, this is where we are going to be writing the main logic of the storing of the login history, inside the handle method, add the following code
public function handle(LoginHistory $event)
{
$current_timestamp = Carbon::now()->toDateTimeString();
$userinfo = $event->user;
$saveHistory = DB::table('login_history')->insert(
['name' => $userinfo->name, 'email' => $userinfo->email, 'created_at' => $current_timestamp, 'updated_at' => $current_timestamp]
);
return $saveHistory;
}
Also remember to call the Carbon and DB facade before the class
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;
Our listener now looks like this
From the listener, we are trying to add the name, email, time created and time updated to a table login_history, that is when any user logs in, it will grab that information and store it in the table.
Step 4: Create the Table and Migrate
I am not going to explain deep on this step, I have some of my articles that explain them, check them out from my profile,
Create migration file
Add your columns to the migration files
Then migrate
We now have our table in the database
Step 5: Dispatch the Event
This is the last step, we need to call the event in the LoginController, if you are using laravel 7, or below, you can create a method in the LoginController.php like this
protected function authenticated() {
$user = Auth::user();
event(new LoginHistory($user));
}
but for this article, I am using Laravel Breeze, a simple UI scaffolding that was released 16 days ago, so I will go to LoginRequest.php found in app/Http/Requests/Auth/LoginRequest.php and inside the authenticate() method, I will call my event and pass the $user to the class
public function authenticate()
{
$this->ensureIsNotRateLimited();
if (! Auth::attempt($this->only('email', 'password'), $this->filled('remember'))) {
RateLimiter::hit($this->throttleKey());
throw ValidationException::withMessages([
'email' => __('auth.failed'),
]);
}
$user = Auth::user();
event(new LoginHistory($user));
RateLimiter::clear($this->throttleKey());
}
I only added $user = Auth::user(); and event(new LoginHistory($user));, notice how I dispatched my event, you can use that or you use this EventClass::dispatch();, but we are using event(new LoginHistory($user));.
So when a user attempts to sign in, if the user is authenticated, the event will then be fired, and the listener will save the history
This is the result, when I sign in twice
Follow me for more of my articles, you can leave comments, suggestions, and reactions.
I am open to any vacancy as a PHP backend engineer, my strength is in the Laravel framework
click the link to view my profile and follow me
Thank you for your time
Top comments (11)
What about testing ?
did you found the article?
Link ? please
Thanks
Great article! Good explanation of SOLID Principle.
Great article. Well explained. Works for me. Thank you!
Thank you !
Good Tutotial .May allah bless you
Thank you. Great article, worked good for my project.
good job!
thanks 🧡