Core

Event Service Provider

Synchronous event dispatcher and listener registration infrastructure.

Responsibility

Registers EventDispatcherInterface and alias events for decoupled domain/application event handling. EventServiceProvider also reads listener definitions from events.listeners config and registers them on the dispatcher.

Listener config

Application listeners are configured in app/Config/Events.php. Keys are event class names, values are listener class lists or callables.

<?php

declare(strict_types=1);

use App\Events\UserRegisteredEvent;
use App\Listeners\SendWelcomeEmailListener;

return [
    'listeners' => [
        UserRegisteredEvent::class => [
            SendWelcomeEmailListener::class,
        ],
    ],
];

Event DTO

Events are plain objects. Keep them small and explicit; they should carry data, not framework dependencies.

namespace App\Events;

final class UserRegisteredEvent
{
    public function __construct(
        private readonly string $email,
    ) {}

    public function email(): string
    {
        return $this->email;
    }
}

Listener

A listener can be any callable. Class-string listeners are resolved through the container, so listener classes can use constructor injection when registered as services or autowired by the container.

namespace App\Listeners;

use App\Events\UserRegisteredEvent;

final class SendWelcomeEmailListener
{
    public function __invoke(UserRegisteredEvent $event): void
    {
        // Handle event here.
    }
}

Dispatching

Prefer constructor injection in services/controllers. Direct container access is useful in factories or examples where the container is already available.

use App\Events\UserRegisteredEvent;
use Lemonade\Framework\Event\EventDispatcherInterface;

final class ExampleService
{
    public function __construct(
        private readonly EventDispatcherInterface $events,
    ) {}

    public function run(): void
    {
        $this->events->dispatch(new UserRegisteredEvent('user@example.test'));
    }
}

Runtime behavior

Events are synchronous: dispatch() invokes matching listeners before returning the event object. The dispatcher matches listeners registered for the exact event class, parent classes and implemented interfaces. Listener priority is available programmatically through addListener($eventClass, $listener, priority: 10); Events.php config registers listeners with default priority.

Events are not queue

EventServiceProvider does not make work asynchronous. Use events for in-process decoupling. For background jobs, retries or workers, use QueueBusInterface and QueueServiceProvider instead.