Kritim Yantra
Apr 04, 2025
Laravel's event system is a powerful tool that helps you build decoupled, maintainable applications. In this deep dive, we'll explore Laravel 12's event handling capabilities through practical examples you can apply directly to your projects.
Imagine building an e-commerce platform. When an order is placed, you need to:
Without events, your order processing code would quickly become a tangled mess. Events let you handle these actions cleanly:
OrderPlaced::dispatch($order);
Generate the event:
php artisan make:event UserRegistered
Create a listener:
php artisan make:listener SendWelcomeEmail --event=UserRegistered
Event Class:
namespace App\Events;
use App\Models\User;
use Illuminate\Foundation\Events\Dispatchable;
class UserRegistered
{
use Dispatchable;
public function __construct(public User $user) {}
}
Listener Class:
namespace App\Listeners;
use App\Events\UserRegistered;
use App\Mail\WelcomeEmail;
use Illuminate\Support\Facades\Mail;
class SendWelcomeEmail
{
public function handle(UserRegistered $event)
{
Mail::to($event->user->email)->send(new WelcomeEmail($event->user));
}
}
Laravel 12 automatically discovers listeners in app/Listeners
, but you might need manual registration for:
// In AppServiceProvider
public function boot()
{
Event::listen(
UserRegistered::class,
[SendWelcomeEmail::class, 'handle']
);
// Conditional listener registration
if (config('app.send_welcome_emails')) {
Event::listen(/* ... */);
}
}
Example: Video Processing
namespace App\Listeners;
use App\Events\VideoUploaded;
use Illuminate\Contracts\Queue\ShouldQueue;
class ProcessVideo implements ShouldQueue
{
public $queue = 'videos';
public $delay = 60; // Wait 1 minute before processing
public function handle(VideoUploaded $event)
{
// Intensive video processing logic
$event->video->process();
}
public function failed(VideoUploaded $event, Throwable $exception)
{
// Notify admin of failed processing
Notification::sendAdmin("Video processing failed: " . $exception->getMessage());
}
}
Ensure events only fire after successful transactions:
class OrderController extends Controller
{
public function store()
{
DB::transaction(function () {
$order = Order::create(/* ... */);
// This event will only dispatch if the transaction commits
OrderCreated::dispatchAfterCommit($order);
});
}
}
User Activity Tracker:
namespace App\Subscribers;
class UserActivitySubscriber
{
public function handleLogin($event) {/* ... */}
public function handleLogout($event) {/* ... */}
public function handleProfileUpdate($event) {/* ... */}
public function subscribe()
{
return [
Login::class => 'handleLogin',
Logout::class => 'handleLogout',
ProfileUpdated::class => 'handleProfileUpdate',
];
}
}
Registration:
Event::subscribe(UserActivitySubscriber::class);
Feature Test Example:
public function test_order_confirmation_email_sent()
{
Event::fake();
$user = User::factory()->create();
$response = $this->post('/place-order', [
// Order details
]);
Event::assertDispatched(OrderPlaced::class, function ($event) use ($user) {
return $event->order->user_id === $user->id;
});
Event::assertNotDispatched(PaymentFailed::class);
}
Testing Queued Listeners:
public function test_video_processing_queued()
{
Bus::fake();
$video = Video::factory()->create();
VideoUploaded::dispatch($video);
Bus::assertDispatched(ProcessVideo::class);
}
class LogUserActivity
{
public function handle($event)
{
ActivityLog::create([
'user_id' => $event->user->id,
'event' => get_class($event),
'data' => $event->getLogData()
]);
}
}
class ClearProductCache
{
public function handle(ProductUpdated $event)
{
Cache::forget("product_{$event->product->id}");
Cache::forget('featured_products');
}
}
class SyncWithCRM implements ShouldQueue
{
public function handle(CustomerUpdated $event)
{
Http::post('crm-api.com/customers', [
'id' => $event->customer->crm_id,
'data' => $event->customer->toArray()
]);
}
}
Naming Conventions:
When to Use Events:
Performance Considerations:
Debugging:
event:list
Artisan commandEvent::listen('*', function ($eventName, $payload) {
Log::debug("Event fired: $eventName", $payload);
});
Laravel's event system is your gateway to building scalable, maintainable applications. By implementing events and listeners effectively, you can:
Remember: While powerful, events shouldn't replace all direct method calls. Use them judiciously where they provide clear architectural benefits.
Ready to supercharge your Laravel applications? Start by identifying one complex process in your current project that could benefit from event-driven architecture, and refactor it using these techniques!
No comments yet. Be the first to comment!
Please log in to post a comment:
Continue with Google