Skip to content
CAI
Software that uses CAICheck a score

prooph/event-sourcing

59.7

Adequate · 22 September 2026

1.3k

lines of production code

PHP

primary language

7

measurements over time

CAI band scale
CAI trend line
CAI lens gauges

What this system is

This system is an event-sourcing library for PHP that provides a structured way to manage aggregate roots and their associated domain events. It offers core abstractions for tracking state changes, persisting events to a store, and reconstructing aggregates from their history. The library includes utilities for dependency injection, exception handling, and integration with event stores, all supported by comprehensive test coverage.

How it got here

2014–2015 — Core event-sourcing implementation

8 changes.

This period focused on establishing the core event-sourcing architecture, introducing key classes like AggregateRoot and AggregateChanged to manage state and domain events. The work included building integration components for event stores and providing a practical example to demonstrate the library's usage. Comprehensive unit tests were added to validate the new functionality.

2016 — Aggregate namespace and repository implementation

5 changes.

This period focused on introducing the new Aggregate namespace, which includes the AggregateRepository class for managing event-sourced aggregates with features like an identity map and configurable stream-per-aggregate behavior. The release also added supporting interfaces, exception types, and a container factory to facilitate dependency injection, accompanied by comprehensive test coverage for these new components.

Features

Add AggregateRepositoryFactory for container-based instantiation

A new factory class, AggregateRepositoryFactory, has been added to the Container/Aggregate namespace. This class implements the Interop Config interfaces (RequiresConfigId, RequiresMandatoryOptions, ProvidesDefaultOptions) to facilitate the creation of AggregateRepository instances via a PSR-11 compatible container. It resolves dependencies such as the event store, aggregate type, and optional snapshot store from the container, allowing for more flexible and decoupled repository instantiation within the dependency injection container.

src/Container · medium confidence

Add PHP quickstart example for event sourcing

A new quickstart example (examples/quickstart.php) is added to demonstrate how to use the Prooph event-sourcing library. The example defines a User aggregate root, domain events (UserWasCreated, UserWasRenamed), and an in-memory repository implementation, illustrating the basic patterns for creating, saving, and retrieving aggregate roots using the library's API.

examples · high confidence

Introduce core event-sourcing classes for aggregate management

Added the AggregateChanged and AggregateRoot classes to the src directory. AggregateChanged extends DomainEvent and manages aggregate state with a version number stored in metadata, while AggregateRoot is an abstract class that uses traits for event production and sourcing.

src · high confidence

Introduce new Aggregate namespace with repository and translator interfaces

Added the \Prooph\\EventSourcing\\Aggregate\ namespace containing the \AggregateRepository\ class, which manages loading and saving event-sourced aggregates via an \EventStore\ and optional \SnapshotStore\. The \AggregateRepository\ now supports an identity map (cacheable aggregate instances), configurable stream-per-aggregate behavior, and metadata enrichment for domain events. Supporting classes include the \AggregateTranslator\ interface, \AggregateType\ for type mapping, \AggregateTypeProvider\ interface, and traits (\EventProducerTrait\, \EventSourcedTrait\) that provide core event-sourcing mechanics like versioning, event recording, and history replay.

src/Aggregate · high confidence

New Aggregate exception types introduced

The library now provides a dedicated set of exception classes for the Aggregate namespace, including an AggregateException interface and specific exceptions such as AggregateTranslationFailedException, AggregateTypeException, InvalidArgumentException, and RuntimeException. These allow for more granular error handling and type-specific exception catching within the event-sourcing aggregate layer.

src/Aggregate/Exception · high confidence

New aggregate translation and decoration classes for EventStore integration

Added three new classes to the \Prooph\\EventSourcing\\EventStoreIntegration\ namespace: \AggregateRootDecorator\, \AggregateTranslator\, and \ClosureAggregateTranslator\. These classes provide mechanisms to extract aggregate metadata (version, ID, events) and reconstruct aggregates from history, supporting both standard and closure-based translation strategies for event store integration.

src/EventStoreIntegration · high confidence

Behavioural changes

Repository configuration and metadata updates

Added configuration files for Travis CI (.travis.yml), code coverage (.coveralls.yml, phpunit.xml.dist), and PHP CS Fixer (.php\_cs) to automate testing and linting. Updated the project's license header (.docheader) and copyright notices (LICENSE, .docheader) to reflect current ownership. Updated the README with installation and usage instructions, and added a CHANGELOG.md to track version history.

(repo-wide) · high confidence

Test coverage

Add unit tests for AggregateChanged and AggregateRoot; Added mock classes for testing event-sourcing aggregates; Added test coverage for Aggregate and AggregateType components; Added tests for AggregateRepositoryFactory; Added tests for EventStoreIntegration components.

Dependencies

Update PHP and Prooph/Event-Store dependencies

The composer.json file has been updated to require PHP 7.3 or 8.0 and Prooph/Event-Store version 7.0 or higher. Additionally, development dependencies such as PHPUnit 9.3, Prophecy, and various Prooph tools have been updated to their latest compatible versions.

(dependencies) · high confidence

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

How this codebase got here

Score

  • CAI 56 → 60 (+3.5)
  • Rubric changed (rubric-2026.08.19 → rubric-2026.09.15) — scores are not directly comparable.

Lenses

  • Code Health 100 → 100 (+0.0)
  • Architecture 69 → 69 (+0.0)
  • Maturity 41 → 49 (+7.7)
  • Readiness 50 → 50 (-0.0)
  • Security 100 → 100 (+0.0)
  • Domain Modelling 100 → 100 (+0.0)
  • Event Sourcing 100 → 100 (+0.0)

Resolved (6)

  • Coverage not included — suite not readable by the collector
  • Dependency hygiene not measured — dependency manifest found but not parsed for hygiene
  • LLM evaluation failed
  • No exposed public API
  • Test reliability not included
  • dormant codebase — no living knowledge left to concentrate

New (10)

  • Dependency hygiene PARTLY measured — Composer dependencies read, no committed lock to grade for currency
  • Documentation: no installation or build instructions (README.md)
  • Documentation: no licence statement (README.md)
  • Documentation: no usage examples (README.md)
  • Duplicate method extractAggregateId exists in both the base AggregateTranslator and the EventStoreIntegration.AggregateTranslator (and its closure variant). While inheritance might explain this, the presence of ClosureAggregateTranslator which duplicates the interface of AggregateTranslator suggests a confusing split between 'standard' and 'closure-based' implementations that offer no clear advantage other than implementation detail, leading to API fragmentation.
  • Duplicate method extractPendingStreamEvents across three translator classes. This is a critical operation for saving aggregates, and having it duplicated increases the risk of inconsistent event extraction logic.
  • Duplicate method replayStreamEvents across three translator classes. This is the core mechanism for applying events to an aggregate. Duplication here is high-risk for consistency.
  • No dependency advisory monitoring
  • Severe duplication of core logic across multiple classes. The method extractAggregateVersion exists on the Repository, the main Translator, the EventStoreIntegration Translator, the ClosureTranslator, and the Decorator. This violates DRY and creates a maintenance nightmare where version extraction logic must be synchronized across five different places.
  • The method reconstituteAggregateFromHistory is duplicated across three translator classes. This indicates that the core logic for rebuilding an aggregate from events is not centralized, risking divergence in behavior between the standard translator and the event-store integration translator.

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

Survey your own repository

prooph/event-sourcing was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.

About this page

  • The score is its most recent published measurement, taken on 22 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
  • Measured at commit 4b8e2e50f9029f0e8006f7c3bbb5c60519f3f4f7 — the exact code this score is about.
  • Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer preprod-821afab8930d.