Skip to content

Laravel - Event Handling

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.

The general workflow involves these steps:

  1. Define an Event Class: Create a class that represents the event. This class typically holds data related to the event.
  2. Define Listener Class(es): Create one or more listener classes that will handle the event once it’s dispatched.
  3. Register Events and Listeners: Map your events to their corresponding listeners in the EventServiceProvider.
  4. Dispatch an Event: Trigger the event from somewhere in your application code.

You can generate a new event class using the Artisan CLI command:

php artisan make:event PodcastProcessed

This 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:

app/Events/PodcastProcessed.php
namespace App\Events;
use App\Models\Podcast; // Assuming you have a Podcast model
use 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.

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=PodcastProcessed

This 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.

app/Listeners/SendPodcastNotification.php
namespace App\Listeners;
use App\Events\PodcastProcessed;
use Illuminate\Contracts\Queue\ShouldQueue; // Optional: for queued listeners
use 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.

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.

app/Providers/EventServiceProvider.php
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.

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 service
use 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.

Let’s consider a common scenario: sending a welcome email when a new user registers.

  1. Event: UserRegistered (e.g., php artisan make:event UserRegistered). This event would carry the User model.

    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; }
    }
  2. 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 WelcomeMail
    class SendWelcomeEmail
    {
    public function handle(UserRegistered $event)
    {
    Mail::to($event->user->email)->send(new WelcomeMail($event->user));
    }
    }
  3. Registration: Add UserRegistered::class => [SendWelcomeEmail::class] to $listen in EventServiceProvider.php.

  4. Dispatch: In your user registration controller, after successfully creating a user:

    // In your Auth Controller or Registration Service
    use 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.