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

Prooph Bundle Laravel Package

proophsoftware/prooph-bundle

Symfony bundle that integrates Prooph's CQRS and event sourcing components, wiring event stores, command and event buses, projections, and service configuration so PHP applications can build domain-driven, event-driven systems with less boilerplate.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimum viable setup for proophsoftware/prooph-bundle v0.1.2:

composer require proophsoftware/prooph-bundle:^0.1.2

v0.1.2 added two hard dependencies worth knowing about before you install:

  • sandrokeil/interop-config — used to register command/query/event handlers from config rather than hand-wiring services.
  • doctrine/doctrine-migrations-bundle — the event store and projection tables are now expected to be created via Doctrine migrations, and the install instructions assume you already have that bundle wired up.

Where to look first:

  1. The bundle's DependencyInjection/Configuration.php (or equivalent config tree) — this is the contract for how you declare command buses, event buses, event stores and projections.
  2. The Resources/config/ service definitions — this tells you which services you can inject and which IDs to alias.
  3. The example/README config block — the v0.1.2 install instructions now assume Doctrine migrations, so follow them in order.

First use case: a single write model. Define one aggregate (RegisterUser), one command, one domain event, register a command handler, and configure a Doctrine-based event store. Don't add projections until you can prove the command → aggregate → event → store loop works end-to-end. That single loop is what the bundle actually buys you; everything else is prooph components you could wire yourself.

Caveat up front: this is a Symfony bundle, not a Laravel package. There is no ProophServiceProvider, no facade, no publishable config. In Laravel you are consuming the configuration patterns and service wiring ideas, plus the underlying prooph components — expect to write a service provider that mirrors what the bundle's extension class does.

Implementation Patterns

Command bus per boundary. Configure at least two buses: a synchronous command bus for immediate validation and an asynchronous one for anything that touches the event store or external systems. Handlers are registered by config key with interop-config, so the mapping lives in config rather than in AppServiceProvider closures.

Aggregate + repository pairing. One EventSourcedRepository per aggregate type, built from an EventStore. Keep repositories out of controllers — inject the command bus into controllers/HTTP layer and let handlers resolve repositories.

Event store via Doctrine. The doctrine/doctrine-migrations-bundle dependency added in v0.1.2 signals that the event store tables are migration-managed. Treat the event store schema as a first-class migration: commit it, version it, and never let doctrine:schema:update touch it.

Projections as separate consumers. Register read-model projectors against the event bus (sync, for small local projections) or against a persistent subscription (async, for anything expensive). In Laravel, async projectors map naturally onto queue workers: one job per subscription poll, or a long-running artisan prooph:projection --name=... command you supervise.

Config-driven handler registration. Because interop-config is now a dependency, the idiomatic pattern is:

// config/prooph.php (translated into a Laravel config array)
'command_bus' => [
    'plugins' => [/* ... */],
    'handlers' => [
        'App\Registration\RegisterUser' => 'App\Registration\RegisterUserHandler',
    ],
],

Resolve these keys in a service provider with $this->app->bind(...) in a loop. The payoff is that adding a handler is a config change, not a container change.

Integration tips for Laravel specifically:

  • Wrap bundle service definitions in a single ProophServiceProvider; expose command_bus, query_bus, event_bus, event_store as singletons.
  • Bind the event store as a singleton — multiple instances means multiple connections and inconsistent transaction boundaries.
  • Use DB::transaction() around the command handler only if you are not using the event store's own transactional wrapper; don't nest them.
  • Publish the handler map as config/prooph.php so it is cacheable with config:cache.

Gotchas and Tips

The v0.1.2 install instructions are load-bearing. Both new dependencies are behavioural, not cosmetic. If you upgrade from v0.1.1 and your composer.json has doctrine/doctrine-migrations-bundle pinned or excluded, Composer will fail or you'll get a container that references migration services that don't exist. Re-read the install instructions after any v0.1.x bump.

interop-config failures surface at container compile time, not runtime. A typo in a handler config key produces an unhelpful "service not found" during config:cache or container build. Keep the handler map small and add a php artisan prooph:debug-handlers-style command of your own if the map grows past ~20 entries.

Pre-1.0 versioning. v0.1.x makes no BC promises. Pin exactly (0.1.2) in composer.json and upgrade deliberately; the release notes for this version are dependency-only, which is a hint that the maintainers are still stabilising the wiring rather than the API.

Doctrine migrations conflict. Adding doctrine/doctrine-migrations-bundle to a Laravel app is unusual — Laravel typically uses its own migrations. Pick one owner for the event store schema. Mixing Laravel migrations and Doctrine migrations on the same database is a reliable source of "table already exists" in CI.

Event serialisation is your problem, not the bundle's. Event store rows are only as portable as the serialiser you configure. Version your event class names explicitly (App\Events\V2\UserRegistered) and never rename an event class without a migration or an upcaster — old rows will fail to deserialize on replay.

Projections are eventually consistent. Do not read from a projection immediately after dispatching a command in the same request. Either return the write model's state from the handler or accept a read-after-write gap.

Replay safety. Projectors must be idempotent. If a projection fails mid-stream, reset the projection (truncate the read table, reset the subscription position) and replay — make sure your projector tolerates seeing the same event twice.

Transaction boundaries. The event store append and any synchronous projection update should share a transaction; async projections obviously cannot. Be explicit about which of your projections are sync, because the answer determines whether a "committed" event is guaranteed visible to a read model.

Extension point: the bundle's compiler passes are where you hook custom buses. If you need a third bus (e.g. a separate query bus with a different middleware stack), copy the pattern from the bundle's extension class rather than inventing a parallel one — this keeps upgrades to v0.2.x tractable.

Ecosystem risk. Prooph v7 is effectively end-of-life and maintenance has moved to community forks. For a greenfield Laravel project, evaluate event-engine/php-engine or a Laravel-native event sourcing package before committing; adopt this bundle when you specifically need prooph's existing components or are inheriting a prooph codebase.

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.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource