Laravel Event Listener

Assume that you want to send the email notification, as a security measure, when someone logs into the application. How can you send this email?
Recall, any service bind with service container can be available to use via a facade. These two communicate each other through the service container with a binding key.
But in Event listener phenomena, Event class and Listener class are bonded directly with each other in EventServiceProvider.php by $listen array. Here, the key of the $listen array is event and value is the listener.
When you create an Event (custom class) and trigger it with event() helper, you don't need to do anything else to catch it in listener. Now, put dd($event) inside the listener's handle() method, you will see the properties and maybe other information too.

Event Listener creating steps:

1. Open app/Providers/EventServiceProvider.php file and register our custom event and listener mappings.
2. Run the command: php artisan event:generate
3. Update the app/Events/ClearCache.php class to give any property or methods (ex. public $cache_keys = [];)
4. Update the handle method of your custom listener to work with the property or method created in step 2.
5. Create a controller which will invoke event helper with an insance of your custom event

Understanding of Event Listener

Here is the app/Providers/EventServiceProvider.php
namespace App\Providers;
use Illuminate\Support\Facades\Event;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
'App\Events\Event' => [
'App\Listeners\EventListener',
],
];
/**
* Register any events for your application.
*
* @return void
*/
public function boot()
{
parent::boot();
//
}
}
Now, Illuminate\Auth\Events\Login is an event that'll be raised when someone logs into an application. We'll bound that event to the App\Listeners\SendEmailNotification listener, so it'll be triggered on the login event.
namespace App\Providers;
use Illuminate\Support\Facades\Event;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
'Illuminate\Auth\Events\Login' => [
'App\Listeners\SendEmailNotification',
],
];
/**
* Register any events for your application.
*
* @return void
*/
public function boot()
{
parent::boot();
//
}
}
After populating $listen array with Event Listener, we will run the following command:
php artisan event:generate
This command generates event and listener classes listed under the $listen property if they do not exist.
In our case, the Illuminate\Auth\Events\Login event already exists, so it only creates the App\Listeners\SendEmailNotification listener class. In fact, it would have created the Illuminate\Auth\Events\Login event class too if it didn't exist.
Let's have a look at the listener class created at app/Listeners/SendEmailNotification.php.
namespace App\Listeners;
use Illuminate\Auth\Events\Login;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendEmailNotification
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param Login $event
* @return void
*/
public function handle(Login $event)
{

}
}
handle method that will be invoked with appropriate dependencies whenever the listener is triggered.

Create a Custom Event

Consider, our application needs to clear caches in our system at certain points. We'll raise the CacheClear event.
Open app/Providers/EventServiceProvider.php file and register our custom event and listener mappings.
namespace App\Providers;
use Illuminate\Support\Facades\Event;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
'App\Events\ClearCache' => [
'App\Listeners\WarmUpCache',
],
];
/**
* Register any events for your application.
*
* @return void
*/
public function boot()
{
parent::boot();
//
}
}
Run the command:
php artisan event:generate
With a few changes, the app/Events/ClearCache.php class should look like this:
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class ClearCache
{
use Dispatchable, InteractsWithSockets, SerializesModels;

public $cache_keys = [];
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(Array $cache_keys)
{
$this->cache_keys = $cache_keys;
}
/**
* Get the channels the event should broadcast on.
*
* @return Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}
Next, let's have a look at the listener class with an updated handle method at app/Listeners/WarmUpCache.php.
namespace App\Listeners;
use App\Events\ClearCache;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class WarmUpCache
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param ClearCache $event
* @return void
*/
public function handle(ClearCache $event)
{
if (isset($event->cache_keys) && count($event->cache_keys)) {
foreach ($event->cache_keys as $cache_key) {
// generate cache for this key
// warm_up_cache($cache_key)
}
}
}
}
Now, create a controller file at app/Http/Controllers/EventController.php to demonstrate how you could raise an event.
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Library\Services\Contracts\CustomServiceInterface;
use App\Post;
use Illuminate\Support\Facades\Gate;
use App\Events\ClearCache;
class EventController extends Controller
{
public function index()
{
// ...

// you clear specific caches at this stage
$arr_caches = ['categories', 'products'];

// want to raise ClearCache event
event(new ClearCache($arr_caches));

// ...
}
}
The event helper function is used to raise an event from anywhere within an application.

What Is an Event Subscriber?

Whenever you want to logically group event listeners, you have to choose Event Subscribers
// app/Listeners/ExampleEventSubscriber.php
namespace App\Listeners;
class ExampleEventSubscriber
{
/**
* Handle user login events.
*/
public function sendEmailNotification($event) {
// get logged in username
$email = $event->user->email;
$username = $event->user->name;

// send email notification about login...
}
/**
* Handle user logout events.
*/
public function warmUpCache($event) {
if (isset($event->cache_keys) && count($event->cache_keys)) {
foreach ($event->cache_keys as $cache_key) {
// generate cache for this key
// warm_up_cache($cache_key)
}
}
}
/**
* Register the listeners for the subscriber.
*
* @param Illuminate\Events\Dispatcher $events
*/
public function subscribe($events)
{
$events->listen(
'Illuminate\Auth\Events\Login',
'App\Listeners\ExampleEventSubscriber@sendEmailNotification'
);

$events->listen(
'App\Events\ClearCache',
'App\Listeners\ExampleEventSubscriber@warmUpCache'
);
}
}
It's the subscribe method that is responsible for registering listeners. The first argument of the subscribe method is the instance of the Illuminate\Events\Dispatcher class that you could use to bind events with listeners using the listen method.
namespace App\Providers;
use Illuminate\Support\Facades\Event;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
/**
* The subscriber classes to register.
*
* @var array
*/
protected $subscribe = [
'App\Listeners\ExampleEventSubscriber',
];
/**
* Register any events for your application.
*
* @return void
*/
public function boot()
{
parent::boot();
//
}
}

Labels: ,

© copyright-2020 Rejaul