Installation and First Steps

Installation

1
composer require ecotone/pdo-event-sourcing
Copied!
And go to DBAL Support in order to configure the connection.
To get started quickly you may find Demo Project useful.
Ecotone Event Sourcing is based on well known and stable Prooph's Event Store. It does provide support for three databases: - PostgreSQL - MySQL - MariaDB

Storing Events in streams using Aggregates

There are two ways, we can make use of Event Sourced Aggregates.

Pure Event Sourced Aggregate

This way of handling events does allow for pure functions. Writes are clearly separated from writes.
1
#[EventSourcingAggregate] // 1
2
class Ticket
3
{
4
use WithAggregateVersioning; // 2
5
6
#[AggregateIdentifier] // 1
7
private string $ticketId;
8
private string $ticketType;
9
10
#[CommandHandler] // 2
11
public static function register(RegisterTicket $command) : array
12
{
13
return [new TicketWasRegistered($command->getTicketId(), $command->getTicketType())];
14
}
15
16
#[CommandHandler] // 2
17
public function close(CloseTicket $command) : array
18
{
19
return [new TicketWasClosed($this->ticketId)];
20
}
21
22
#[EventSourcingHandler] // 4
23
public function applyTicketWasRegistered(TicketWasRegistered $event) : void
24
{
25
$this->ticketId = $event->getTicketId();
26
$this->ticketType = $event->getTicketType();
27
}
28
}
Copied!
  1. 1.
    EventSourcingAggregate and AggregateIdentifier works exactly the same as State-Stored Aggregate.
  2. 2.
    Event Sourced Aggregate must provide version. You may leave it to Ecotone using WithAggregateVersioning or you can implement it yourself.
  3. 3.
    CommandHandlerfor event sourcing returns events generated by specific method. This will be passed to the Repository to be stored.
  4. 4.
    EventSourcingHandler is method responsible for reconstructing Aggregate from previously created events. At least one event need to be handled in order to provide AggregateIdentifier.

Internal Recorder Aggregate

This way of handling events allow for similarity with State Stored Aggregates.
1
#[EventSourcingAggregate(true)] // 1
2
class Basket
3
{
4
use WithAggregateEvents;
5
use WithAggregateVersioning;
6
7
#[AggregateIdentifier]
8
private string $id;
9
10
#[CommandHandler] // 2
11
public static function create(CreateBasket $command) : static
12
{
13
$basket = new static();
14
$basket->recordThat(new BasketWasCreated($command->getId()));
15
16
return $basket;
17
}
18
19
#[CommandHandler] // 2
20
public function addProduct(AddProduct $command) : void
21
{
22
$this->recordThat(new ProductWasAddedToBasket($this->id, $command->getProductName()));
23
}
24
25
#[EventSourcingHandler]
26
public function applyBasketWasCreated(BasketWasCreated $basketWasCreated)
27
{
28
$this->id = $basketWasCreated->getId();
29
}
30
}
Copied!
  1. 1.
    In order to make use of alternative way of handling events, we need to set attribute to trueEventSourcingAggregate(true)
  2. 2.
    Command Handlers instead of returning events are acting the same as State Stored Aggregates. All events which will be published using recordThatwill be passed to the Repository to be stored.