digitalrisks/laravel-eventstore
A Laravel event store for event sourcing: persist domain events, rebuild aggregates from stored streams, and keep an auditable history of every change. Integrates with Laravel's database and service container.
composer require gosuperscript/laravel-eventstore, then publish the package config and migrations (php artisan vendor:publish --tag=eventstore-config / --tag=eventstore-migrations) and run php artisan migrate. The event store persists to a relational table, so decide up front whether it lives on your default connection or a dedicated one.config/eventstore.php (connection, table names, snapshot/projection settings) and the package README's "Aggregate" example. Everything else — projectors, reactors, replays — is a layer on top of the stored-events table.Account with open/deposit/withdraw) and wire it end to end: record events on the aggregate, persist them, then rebuild the aggregate from its event stream and assert the state matches. Doing this before adding projectors catches serialization and versioning issues early.aggregate_uuid + aggregate_version ordering is what you expect.recordThat() a domain event. State changes belong in the apply* methods so that replaying the stream reconstructs the same object. Persist via the package's repository/EventStore facade rather than inserting rows yourself.projection:replay is safe.ConnectionLostException instead of a plain Exception when the store connection drops (issue #33). Import and catch that type explicitly in long-running consumers (queue workers, reactors, console replay commands) so you can reconnect and retry rather than letting the job die. Because it still extends Exception, existing broad catch (\Exception $e) blocks keep working — which means you may not notice the change; audit those catch blocks and narrow them where retry semantics matter. Note the changed type in any instanceof checks or exception-mapping middleware.failed()/retryUntil() and any global exception handler distinguish connection loss (retryable) from domain/validation failure (not retryable). A dropped connection should never be recorded as a permanent failure.DB::reconnect() or rely on the new exception to detect and recover.event_version) the moment you need to change a field. Never mutate a released event's shape in place.projection:status-style command; a projector that quietly stops advancing looks identical to one with nothing to do.How can I help you explore Laravel packages today?