#[Aggregate], #[AggregateIdentifier], aggregate command handlers, repository abstraction, #[Saga] as process managers, bounded-context isolation via Distributed Bus, Domain Events as first-class plain PHP classes.
Composer package · Laravel, Symfony, or Tempest · PostgreSQL or MySQL · RabbitMQ, Kafka, SQS, Redis, or DBAL outbox
Command, query, and event bus — all auto-wired from your attributes. No registration, no factory classes, no container bindings.
Store events, not state. Aggregates, projections, replay, snapshotting. Partitioned + streaming projections so rebuilds parallelize across workers and catch up in real time — no single-process bottleneck.
Stateful long-running processes with compensation. Handler-chaining workflows for stateless pipelines. Saga timeouts in one #[Delayed] attribute. All declarative, all attribute-driven.
Aggregate publishes event. Saga subscribes by attribute. Projection subscribes by attribute. Async handler subscribes by attribute. The attribute is the wiring.
Same aggregates, handlers, sagas, and projections run on Laravel, Symfony, Tempest, or any PSR-11 container. Hedge against framework changes over a decade.
Each tool below is a capable choice for its slice. Ecotone covers the same ground and adds the operational layer around it — so aggregates, projections, sagas, and messaging share one model and one set of guarantees.
Ergonomic event sourcing for Laravel domains.
Where Ecotone goes further than this library
#[Aggregate], #[EventSourcingAggregate], command handlers on aggregate methods — on Laravel or Symfony.#[Saga] adds an identifier-mapped process manager that lives across events arriving over time.Clean DDD ergonomics with trait-based aggregates.
Where Ecotone goes further than this library
#[Saga] as a first-class identifier-mapped process manager.Strong attribute-based aggregate modelling.
Where Ecotone goes further than this library
#[Saga] as a first-class identifier-mapped process manager across events arriving over time.DDD vocabulary as PHP attributes — no base classes, no DSL between domain and framework.
#[Aggregate].#[EventSourcingAggregate] and #[EventSourcingHandler] event-application methods.#[Saga] with #[Identifier] mapping events to instances by payload field, header, or expression.recordThat() mixin, no DomainEventInterface to implement, no library-specific event dispatcher to wire.Haven’t found what you’re looking for? Contact us
Unleash the power of Messaging in PHP
and push productivity to the higher level
