What are event subscribers? Before learning Laravel event subscribers make sure to learn Laravel events. Normally you can define a listener class for events you create. For example postUpdated event can have PushNotification listener. Also PushNotification listener can listen to many events. There is problem when one listener class listen to many events. Whenever event is fired it triggers the handle() method of the listener class. It is okay if all those events need to run same set of code. What to do if you want to run different set of codes for every event. You can create different listener class for every event.
Creating many listener classes is not a good practice. Because it will be harder to maintain your code if you have large number of events. You can use event subscribers where its ultimate goal is to group all your events making it easier to manage and update.
Reason for using Event Subscribers
Case 1
Imagine your project has more than 100 events. You want to group those events. First set of events has 10 event classes and listen by a single listener class. Every event in that group need to execute different set of code. That’s where you can use Event subscriber feature to redirect events reach to the defined listener class to relevant method.
Case 2
Imagine there are 10 events classes and you want to include all those 10 events in a single listener class since all those events are related to one another. Next issue is that listener class should execute different set of codes for every event fired instead of running same set of code. By default Laravel trigger handle() method of the listener class. Using if else to identify event and run different set of codes will create a mess. Laravel has introduce Event Subscribers to have more clean approach. Main purpose of this feature is to group events. That make it easier manage large number of events easily via a single listener class.
How to use Event Subscribers
Task
- Create 5 events
- Create one listener
- Use created listener class to listen on all 5 events and make sure to run different set of code for every event.
Step 1: Create 5 events
Let’s create 5 events using artisan command.
php artisan make:event CommentPosted
php artisan make:event ItemShipped
php artisan make:event OrderPlaced
php artisan make:event ProductAddedToCart
php artisan make:event ProfileUpdated
Step 2: Create a listener class
Create a listener class to listen for above 5 events.
php artisan make:listener UserEventSubscriber
Step 3: Convert created listener class to a subscriber class.
You have to do 2 things to convert normal event listener class to event subscriber class.
- Register this listener class in AppServiceProvider as a Event Subscriber.
- Create separate handle method for every event.
- Add subscribe method to the listener to bind handlers and events.
Lets register the listener class as a event subscriber class. Open AppServiceProvider.php file and register your listener class under boot method.
<?php
namespace App\Providers;
use App\Listeners\UserEventSubscriber;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
//
}
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Event::subscribe(UserEventSubscriber::class);
}
}
Next open your listener class which is UserEventSubscriber.php and create 5 handle() methods to handle above 5 events.
class UserEventSubscriber
{
//handle the comment posted event.
public function handleCommentPosted(object $event): void
{
echo "handle Comment Posted event";
}
//handle the Item Shipped event.
public function handleItemShipped(object $event): void
{
echo "handle Item Shipped event";
}
//handle order Placed event.
public function handleOrderPlaced(object $event): void
{
echo "handle Order Placed event";
}
//handle Producet Added To Cart event
public function handleProducetAddedToCart(object $event): void
{
echo "handle Producet Added To Cart event";
}
//handle Profile Updated event
public function handleProfileUpdated(object $event): void
{
echo "handle Profile Updated event";
}
}
Now bind above 5 handlers to events inside subscribe method. Subscribe() is a predefined method by Laravel.
....
use Illuminate\Events\Dispatcher;
....
public function subscribe(Dispatcher $events): array
{
//Index will be the event class
//value will be the name of the handler method
return [
CommentPosted::class => 'handleCommentPosted',
ItemShipped::class => 'handleItemShipped',
OrderPlaced::class => 'handleOrderPlaced',
ProductAddedToCart::class => 'handleProducetAddedToCart',
ProfileUpdated::class => 'handleProfileUpdated'
];
}
Final version of the UserEventSubscriber.php will look like this.
<?php
namespace App\Listeners;
use App\Events\CommentPosted;
use App\Events\ItemShipped;
use App\Events\OrderPlaced;
use App\Events\ProductAddedToCart;
use App\Events\ProfileUpdated;
use Illuminate\Events\Dispatcher;
class UserEventSubscriber
{
//handle the comment posted event.
public function handleCommentPosted(object $event): void
{
echo "handle Comment Posted event";
}
//handle Item Shipped event
public function handleItemShipped(object $event): void
{
echo "handle Item Shipped event";
}
//handle Order Placed event
public function handleOrderPlaced(object $event): void
{
echo "handle Order Placed event";
}
//handle Producet Added To Cart event
public function handleProducetAddedToCart(object $event): void
{
echo "handle Producet Added To Cart event";
}
//handle Profile Updated event
public function handleProfileUpdated(object $event): void
{
echo "handle Profile Updated event";
}
public function subscribe(Dispatcher $events): array
{
return [
CommentPosted::class => 'handleCommentPosted',
ItemShipped::class => 'handleItemShipped',
OrderPlaced::class => 'handleOrderPlaced',
ProductAddedToCart::class => 'handleProducetAddedToCart',
ProfileUpdated::class => 'handleProfileUpdated'
];
}
}
Dispatch above events and see those are working. Open web.php file in the routes folder and dispatch above events.
<?php
use App\Events\CommentPosted;
use App\Events\ItemShipped;
use App\Events\OrderPlaced;
use App\Events\ProductAddedToCart;
use App\Events\ProfileUpdated;
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
CommentPosted::dispatch();
ItemShipped::dispatch();
OrderPlaced::dispatch();
ProductAddedToCart::dispatch();
ProfileUpdated::dispatch();
});