Laravel - Event Handling
Laravel - Events and Listeners
Section titled “Laravel - Events and Listeners”Laravel’s events provide a simple observer pattern implementation, allowing you to subscribe and listen for various events that occur in your application. 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.
Workflow for Events and Listeners
Section titled “Workflow for Events and Listeners”The general workflow involves these steps:
- Define an Event Class: Create a class that represents the event. This class typically holds data related to the event.
- Define Listener Class(es): Create one or more listener classes that will handle the event once it’s dispatched.
- Register Events and Listeners: Map your events to their corresponding listeners in the
EventServiceProvider. - Dispatch an Event: Trigger the event from somewhere in your application code.
Step 1: Creating an Event Class
Section titled “Step 1: Creating an Event Class”You can generate a new event class using the Artisan CLI command:
php artisan make:event PodcastProcessedThis command will create a new file, for example, app/Events/PodcastProcessed.php. An event class is typically a simple data container. For instance, our PodcastProcessed event might hold the Eloquent model of the podcast that was processed:
namespace App\Events;
use App\Models\Podcast; // Assuming you have a Podcast modeluse Illuminate\Broadcasting\InteractsWithSockets;use Illuminate\Foundation\Events\Dispatchable;use Illuminate\Queue\SerializesModels;
class PodcastProcessed{ use Dispatchable, InteractsWithSockets, SerializesModels;
public Podcast $podcast;
/** * Create a new event instance. * * @param \App\Models\Podcast $podcast * @return void */ public function __construct(Podcast $podcast) { $this->podcast = $podcast; }}Note: The SerializesModels trait will gracefully serialize any Eloquent models if the event object is serialized, such as when using queued listeners. The Dispatchable trait allows the event to be dispatched easily.
Step 2: Creating Listener Classes
Section titled “Step 2: Creating Listener Classes”Next, you need one or more listeners to handle the event. You can generate a listener using the Artisan command:
php artisan make:listener SendPodcastNotification --event=PodcastProcessedThis will create app/Listeners/SendPodcastNotification.php. The --event option will type-hint the PodcastProcessed event in the listener’s handle method. Within the handle method, you can perform actions in response to the event.
namespace App\Listeners;
use App\Events\PodcastProcessed;use Illuminate\Contracts\Queue\ShouldQueue; // Optional: for queued listenersuse Illuminate\Queue\InteractsWithQueue; // Optional: for queued listeners// use Illuminate\Support\Facades\Mail; // Example usage
class SendPodcastNotification // implements ShouldQueue // Optional{ // use InteractsWithQueue; // Optional
/** * Create the event listener. * * @return void */ public function __construct() { // }
/** * Handle the event. * * @param \App\Events\PodcastProcessed $event * @return void */ public function handle(PodcastProcessed $event) { // Access the podcast from $event->podcast // For example, send an email notification: // Mail::to($event->podcast->user_email)->send(new PodcastReadyNotification($event->podcast));
logger('Podcast processed: ' . $event->podcast->title); }}Listeners can also be queued by implementing the ShouldQueue interface. This is useful for tasks that can be performed in the background.
Step 3: Registering Events and Listeners
Section titled “Step 3: Registering Events and Listeners”The EventServiceProvider (located at app/Providers/EventServiceProvider.php) is where you register your event listeners. It contains a $listen array property to map events to their listeners.
namespace App\Providers;
use App\Events\PodcastProcessed;use App\Listeners\SendPodcastNotification;use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;// use Illuminate\Support\Facades\Event; // Not needed for simple $listen array usage
class EventServiceProvider extends ServiceProvider{ /** * The event to listener mappings for the application. * * @var array<class-string, array<int, class-string>> */ protected $listen = [ PodcastProcessed::class => [ SendPodcastNotification::class, // You can add more listeners for the same event here // e.g., App\Listeners\UpdatePodcastAnalytics::class, ], // Other events and their listeners... ];
/** * Register any events for your application. * * @return void */ public function boot() { // }
/** * Determine if events and listeners should be automatically discovered. * * @return bool */ public function shouldDiscoverEvents() { return false; // Set to true for automatic discovery if preferred }}If you generated your listeners with the --event option, Laravel might have already added this mapping for you. Otherwise, add your event and its listener(s) to the $listen array.
Step 4: Dispatching an Event
Section titled “Step 4: Dispatching an Event”To dispatch an event, you can use the event helper function or the Event facade’s dispatch method. Typically, you’ll dispatch events after a certain action has completed.
// Example in a controller or serviceuse App\Events\PodcastProcessed;use App\Models\Podcast; // Assuming you have a Podcast model
// ... elsewhere in your code, after a podcast is processed ...$podcast = Podcast::find(1);if ($podcast) { // Using the event helper event(new PodcastProcessed($podcast));
// Or, if your event class uses the Dispatchable trait: // PodcastProcessed::dispatch($podcast);}When the event is dispatched, Laravel will call the handle method of all registered listeners for that event, passing them the event instance.
Example Scenario: New User Registration
Section titled “Example Scenario: New User Registration”Let’s consider a common scenario: sending a welcome email when a new user registers.
-
Event:
UserRegistered(e.g.,php artisan make:event UserRegistered). This event would carry theUsermodel.app/Events/UserRegistered.php namespace App\Events;use App\Models\User;use Illuminate\Foundation\Events\Dispatchable;use Illuminate\Queue\SerializesModels;class UserRegistered{use Dispatchable, SerializesModels;public User $user;public function __construct(User $user) { $this->user = $user; }} -
Listener:
SendWelcomeEmail(e.g.,php artisan make:listener SendWelcomeEmail --event=UserRegistered). This listener would use Laravel’s Mail functionality.app/Listeners/SendWelcomeEmail.php namespace App\Listeners;use App\Events\UserRegistered;use Illuminate\Support\Facades\Mail;use App\Mail\WelcomeMail; // Assuming you create a Mailable: php artisan make:mail WelcomeMailclass SendWelcomeEmail{public function handle(UserRegistered $event){Mail::to($event->user->email)->send(new WelcomeMail($event->user));}} -
Registration: Add
UserRegistered::class => [SendWelcomeEmail::class]to$listeninEventServiceProvider.php. -
Dispatch: In your user registration controller, after successfully creating a user:
// In your Auth Controller or Registration Serviceuse App\Events\UserRegistered;use App\Models\User;// ...$user = User::create($validatedData);event(new UserRegistered($user));// or UserRegistered::dispatch($user);// ...
This setup ensures that whenever a new user is registered and the UserRegistered event is dispatched, the SendWelcomeEmail listener will automatically be invoked to send the welcome email. This decouples the email sending logic from the registration process itself.
Events and listeners are a powerful tool for building robust, maintainable, and scalable Laravel applications. For more advanced topics like event subscribers, queued listeners, and broadcasting events, consult the official Laravel documentation.