patchlevel/event-sourcing-admin-bundle
Patchlevel Event Sourcing Admin Bundle adds a Symfony admin UI for event-sourced apps: browse aggregates and events, inspect projections, replay or rebuild state, and debug your event store from one dashboard.
First, a reality check that shapes everything else: patchlevel/event-sourcing-admin-bundle is a Symfony bundle, not a Laravel package. It has no service provider, no config/event-sourcing-admin.php, and no artisan commands. It is built on top of patchlevel/event-sourcing, which is usable from Laravel as a plain library. So a Laravel developer's day-to-day path is:
patchlevel/event-sourcing for the event store (aggregate roots, repositories, subscriptions). That is where the real work happens.composer require patchlevel/event-sourcing-admin-bundle:1.0.0-alpha8, register it in config/bundles.php, and import the bundle routing.Where to look first:
src/Controller — these query the event store directly and are the best documentation of what is queryable and how filters are named.First use case: point it at a development or staging event store, open the events listing, filter by a specific aggregate ID, and read the stream in order to reconstruct why a projection ended up in a bad state. Export the stream to CSV and diff it against the same stream from the previous release — that is the fastest "what changed in this bug report" workflow the bundle enables.
Gate it hard. The UI is read-only but it renders full event payloads, which routinely contain PII and internal IDs. Mount it only in local/staging, or wrap every route in your auth middleware. In Symfony use access_control; in a Laravel port use auth plus a can:viewEventStore gate. Do not ship it to production without an explicit decision.
Point it at a read replica. The bundle queries the same connection the app uses. In staging, configure a replica or a restored snapshot so an unfiltered listing cannot hammer the primary during an incident — which is exactly when you will be tempted to use it.
Debugging loop. Reproduce the bug → grab the aggregate ID from logs → open that aggregate's stream → inspect payloads in order → compare with the projection's current row. The CSV export (see below) turns this into a diffable artifact you can attach to a ticket.
CSV export for release comparisons. Since 1.0.0-alpha8 the export explicitly sets the escape character to the empty string. If you automate this, treat the export as a stable interface: fetch it before and after a deploy and diff the two files to spot events that changed shape.
Query-string filters. Filters are plain GET parameters (?aggregate=…&event=…). 1.0.0-alpha8 changed request access to use explicit query/attribute lookups rather than $request->get(). This matters for you because it makes the filters behave consistently under sub-requests, ESI/fragments, and Twig render() includes — a real source of "filter works on one page, not another" bugs.
CI smoke test. The endpoints are unauthenticated-internals GET routes, so in a test environment you can curl them to assert an event stream actually exists after a replay or migration. Cheap, and catches "the projector silently wrote nothing" regressions.
composer require this into Laravel expecting a dashboard is wasted. Port the controllers (they are small) or run it in a Symfony sidecar.1.0.0-alpha8 follows alpha7 with two lock-file-only dependency bumps and two small fixes. That cadence — frequent, tiny releases — is normal here. Pin the exact version (:1.0.0-alpha8), and read the diff before bumping. Semver gives you no guarantees pre-1.0.Request::get() change is subtly breaking for forks. If you copied the controllers or overrode templates, parameters previously pulled via $request->get() are now read from query and attributes explicitly. A value that only ever existed in request (POST body) will no longer be picked up. Re-check any custom filter you added.escape = '', embedded quotes are doubled per RFC 4180 rather than backslash-escaped. Modern Excel and most BI importers are fine; older Excel versions and some ERP importers are not. Test the consumer before you make exports part of a reporting pipeline.How can I help you explore Laravel packages today?