gember / event-sourcing
Use case driven EventSourcing - Let go of the Aggregate with the Dynamic Consistency Boundary (DCB) pattern.
Requires
- php: ^8.3
- composer-runtime-api: ^2.0
- ext-mbstring: *
- ext-tokenizer: *
- gember/dependency-contracts: ^0.9
- psr/log: ^3.0
- psr/simple-cache: ^3.0
Requires (Dev)
- captainhook/captainhook: ^5.23
- friendsofphp/php-cs-fixer: ^3.64
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^12.1
- rector/rector: ^2.0
- rregeer/phpunit-coverage-check: ^0.3.1
- scrutinizer/ocular: ^1.9
- shipmonk/composer-dependency-analyser: ^1.7
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-main
- 0.22.0
- 0.21.1
- 0.21.0
- 0.20.0
- 0.19.1
- 0.19.0
- 0.18.0
- 0.17.0
- 0.16.0
- 0.15.0
- 0.14.0
- 0.13.1
- 0.13.0
- 0.12.0
- 0.11.0
- 0.10.0
- 0.9.0
- 0.8.0
- 0.7.0
- 0.6.0
- 0.5.0
- 0.4.0
- 0.3.0
- 0.2.0
- 0.1.0
- dev-deploy-docs-on-release
- dev-remove-scrutinizer
- dev-add-upgrade-guide
- dev-remove-friendly-class-namer-from-cache
- dev-versioned-snapshots
- dev-versioned-cache-keys
- dev-remove-core-note-from-upgrading
- dev-harden-reflector-and-registries
- dev-enforce-use-case-domain-tags
- dev-docs-review
- dev-outbox-retry-backoff
This package is auto-updated.
Last update: 2026-11-01 20:08:43 UTC
README
Use case driven EventSourcing - Let go of the Aggregate with the Dynamic Consistency Boundary (DCB) pattern.
Documentation
Full documentation is available at gemberphp.github.io/event-sourcing.
Upgrading? See UPGRADE.md.
In a nutshell
Traditional 'Aggregate driven' EventSourcing
Domain concepts are modeled towards objects: the aggregate.
- Any business logic related to a single domain object should live inside the aggregate
- Logic that involves other domain objects or groups of the same kind of domain objects does not belong in the aggregate
'Use case driven' EventSourcing
Domain concepts are modeled through use cases.
- Any business logic tied to a use case should live inside that use case
- A use case can relate to one or more domain concepts
A simple example
A use case that subscribes a student to a course, protecting its rule against both the course's and the student's events:
final class SubscribeStudentToCourse implements EventSourcedUseCase { use EventSourcedUseCaseBehaviorTrait; #[DomainTag] private CourseId $courseId; #[DomainTag] private StudentId $studentId; private bool $isSubscribed = false; #[DomainCommandHandler] public function __invoke(SubscribeStudentCommand $command): void { if ($this->isSubscribed) { return; } $this->apply(new StudentSubscribedEvent((string) $this->courseId, (string) $this->studentId)); } // #[DomainEventSubscriber] methods rebuild the state from past events }
See the full example with domain events and a saga, Getting started, and the demo application gember/example-event-sourcing-dcb.

