Would you like to start using Event Sourcing in PHP, however you don't feel like you have enough knowledge?
Maybe you have started demo project and the tools were to complex to make learning process enjoyable?
Or you don't know what is this about and you would like to find out?
If so, then this Blog Post is here to help you get started with Event Sourcing in PHP.
What is Event Sourcing?
Event sourcing is a way to store the particular state in series of events.
To see the difference between standard approach, let's take a look on Product Entity.
In this example we are having stateful Entity. This Entity allows us to change the price of the product. We do it by replacing old price.
However if any client will argue that when he bought the product it was 10 $ cheaper. We will be having difficulties verifying that.
Event Sourcing on other hand provide answer to such questions by design. You implement the Entity and get possibility to look into the past, because the state is delivered from everything that happened.
Instead of changing Entity State directly we are returning Event which is fact, about what just happened.
This way we can grab the event and store it in our database.
So how the state get actually modified?
By providing methods that take the events and modify state.
Thanks to that, when we load the events from database, we can call related methods and populate Entity state.
Event Sourcing To Answer Your Deepest Questions
We wanted to verify if client was correct, that the price should be 10 $ lower than the price he had to pay. How can we do it?
If we would store the events with date when specific event occurred, then we could go through them and see what was the price at specific moment of time.
Let's take another example.
Suppose that our Manager would like to know what was exact price difference between each price change.
It would be good to make the calculations for him, so he can directly see the answer without using calculator.
In such situations Projections comes to the rescue.
Projections are like stateful entities built from events, designed for answering questions or providing data for views.
We have created Projection, where whenever Price is changed, we are updating it.
Answering Manager's question about how the price is changing, becomes matter of querying the Projection as the answer is already prepared from the events.
Normally you would store it in some database, however for example purpose we will keep In Memory implementation.
We will be using Ecotone together with Prooph's Event Store.
Together they works as glue code, so you can focus on things that matter, business functionalities and flows.
Ecotone together with Prooph's Event Store lower the barrier of building Event Sourced Applications in PHP, so it becomes fun and enjoyable experience.
- First we need to mark our Entity as #[EventSourcingAggregate].
This will tell Ecotone that Product should be used for Event Sourcing.
If you wonder what Aggregate is, you may think of it as Entity having behaviour.
- #[AggregateIdentifier] describes what property is identifier of the Entity.
- useWithAggregateVersioning add versioning to events, as it's required for Prooph
- #[CommandHandler] describes possible actions on your Entity
- #[EventSourcingHandler] describes actions to restore Entity state from events
Before we will call our Entity with commands, let's also build Projection for requirement from our Manager.
- #[Projection("price_change_over_time", Product::class)] This tells Ecotone, that class is Projection named "price_change_over_time", that should use events from Product.
- #[QueryHandler("product.getPriceChange")] this allow us to query Projection using routing key "product.getPriceChange".
- #[EventHandler] describes what events is this Projection interested in
How does it all play together?
Command Handlers are called from Command Bus, the returned events are stored in database and Event Sourcing Handlers and Projections are called from saved events.
So let's execute the example:
Ecotone and Prooph provides all necessary components for you to build Event Sourced Applications in PHP. You may store events in Memory / PostgreSQL / MySQL / MariaDB.
Thanks to combination of those two Frameworks, you can focus directly on business logic leaving the glue code to Ecotone and Prooph.
If you want to see full implementation of this example, you can find it in here.