Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Event Base Laravel Package

rundum/event-base

rundum/event-base gives Laravel developers a lightweight foundation for event-driven code, offering base event classes and helpers for defining, dispatching, and organizing domain events consistently across an application.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Symfony-first package (not Laravel), so treat the first hour as reconnaissance rather than integration.

  1. Install and read the source before the README. There is no meaningful documentation surface for a package at this maturity level. composer require rundum/event-base, then immediately open vendor/rundum/event-base/src/ and composer.json. You are looking for three things:
    • the base event class/interface (likely an abstract Event or a marker interface),
    • whether it ships a Symfony Bundle class (*Bundle.php) that must be registered in config/bundles.php, or whether it is a plain library you wire yourself,
    • its symfony/event-dispatcher constraint — this tells you which Symfony versions it was actually tested against and is your best compatibility signal.
  2. Check what it adds over symfony/event-dispatcher. The description is "basic events for symfony projects," so the value is almost certainly a thin convention layer: a base event class, possibly an event-name convention, a recording trait, or a dispatcher decorator. If it is only a marker interface, you may decide plain Symfony events are enough and skip the dependency entirely.
  3. First use case — one domain event end to end. Pick a single state change in your app (e.g. OrderPlaced), extend/implement the package's base event, dispatch it from your service after the unit of work completes, and handle it in one listener. That one loop will teach you the package's conventions faster than any doc.
// app/Event/OrderPlaced.php
final class OrderPlaced extends BaseEvent // <- whatever the package's base type is
{
    public function __construct(public readonly string $orderId) {}
}
# config/services.yaml — required, autoconfigure does NOT tag third-party subscribers for you
services:
    _defaults:
        autowire: true
        autoconfigure: true
        public: false
    App\:
        resource: '../src/'

Implementation Patterns

Constructor-inject the dispatcher, never the container. Whether you use the package's dispatcher wrapper or Symfony's EventDispatcherInterface, inject EventDispatcherInterface into the service that owns the state change so the dispatch site is explicit and testable.

Record-then-dispatch (unit-of-work pattern). The most useful day-to-day pattern with any Symfony event base is to collect events on your entity and release them after the write succeeds:

final class Order
{
    private array $events = [];

    public function place(): void
    {
        // ... mutate state
        $this->events[] = new OrderPlaced($this->id);
    }

    public function releaseEvents(): array
    {
        $events = $this->events;
        $this->events = [];
        return $events;
    }
}

Then flush a single place: a Doctrine postFlush listener, a repository decorator, or an application service. This avoids dispatching events for transactions that later roll back.

Listeners vs. subscribers. Use EventSubscriberInterface when a class handles several events or you want the event map co-located; use a plain callable listener when it handles one event and you register it in services.yaml. Subscribers only get auto-tagged with autoconfigure: true and must be in the App\ resource glob — a common silent failure.

Priorities for cross-cutting concerns. Register audit/metrics listeners at a high priority so they run before business listeners, and give each listener a single responsibility. Do not let one listener both persist and send mail — the send will run even when persistence throws.

Bridge to Laravel deliberately. Laravel's Illuminate\Contracts\Events\Dispatcher is not PSR-14/Symfony-compatible. If you want this package inside a Laravel app, install symfony/event-dispatcher and register the Symfony dispatcher as a singleton in a service provider, then dispatch Symfony events from your domain layer while leaving framework events (Eloquent\*, Illuminate\*) on Laravel's dispatcher. Mixing them produces "listener never fires" bugs that are hard to see.

Test with a collecting dispatcher. Assert on dispatched events rather than on listener side effects:

$dispatcher = new class extends EventDispatcher {
    public array $dispatched = [];
    public function dispatch(object $event, ?string $name = null): object
    {
        $this->dispatched[] = $event;
        return parent::dispatch($event, $name);
    }
};

Inject that into your service and assert OrderPlaced was recorded once, with the right payload.

Gotchas and Tips

  • This is not a Laravel package. No service provider, no facade, no config/event-base.php. Everything is wiring you own. Budget for that or skip it if you are Laravel-only.
  • Zero stars, zero dependents, last release Aug 2024. Treat it as a small, unmaintained-ish dependency: pin an exact version ("rundum/event-base": "1.0.*"), and be prepared to vendor/fork it. Read every line of src/ — at this size that is 10 minutes and it removes all guesswork about the base class contract.
  • Verify the base event API from source, not from assumptions. Whether the base class is an interface, an abstract with a name() method, or carries a stopPropagation helper changes how you write every event. Do not model your domain events on a guessed contract.
  • Doctrine transaction ordering. Dispatching inside preFlush/onFlush means events fire for writes that may roll back. Prefer postFlush and clear the collected events afterward — otherwise a retried flush re-dispatches duplicates.
  • Queued/async listeners need serializable events. If you route listeners through Symfony Messenger, your event objects must survive serialization. Avoid closures, entities with lazy proxies, and non-serializable services in event payloads — pass scalars and IDs.
  • autoconfigure: true is mandatory for subscriber tagging in services.yaml; without it EventSubscriberInterface classes are instantiated but never registered. This is the #1 "the package is broken" false alarm.
  • Recursion. A listener that dispatches the same event class will loop. Guard with a flag on the event or a separate, distinctly named event.
  • Extension points worth knowing: decorate the dispatcher (implements EventDispatcherInterface, delegates to the inner one) to add logging, correlation IDs, or a dev-mode event timeline; and extend the package's base event class once in your app (App\Event\BaseEvent) so a future swap of the upstream base is a one-file change.
  • Debugging: debug:event-dispatcher (Symfony) lists every registered listener and its priority — if your listener is missing there, it is a wiring/tag problem, not a package problem.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings