Back to all blogposts

CQRS and Event Sourcing implementation in PHP (2/4)

Michał Żądło

Michał Żądło

Head of PHP Team

In the first part of the article about CQRS and Event Sourcing implementation in PHP, I’ve focused on explaining what are CQRS and Event Sourcing. I’ve mentioned the general idea of CQRS, Event Sourcing and Event Store. Also, I’ve presented their pros and cons. The second part of the article is about the implementation of the Write Model with Broadway library.


Let’s imagine that you need to implement a module to handle users in an application. They need to be able to log in and browse through the list of all the registered users.

According to the idea presented in the first part of the article, you divide the app into two parts. First will be responsible for saving and managing the users, the other will be delivering a simple list which includes some basic data and enabling logging in.

Step-by-step implementation of the Write Model

So, your task is to implement a functionality which allows adding users to the repository. Let’s check what we need:

  • CreateUserCommand – a command to add a user,
  • CreateUserHandler – a handler to process a command,
  • UserWasCreatedEvent – an event which confirms a user creation,
  • UserAggregateRoot – a user domain object,
  • UserRepository – a repository to save an object.


The command is a class containing only the fields which are necessary to create a user. You can compare it to a traditional request you submit in the office. This kind of request needs to be filled and passed to be processed.


The handler is responsible for processing a request (CreateUserCommand). It’s a place where you can find the logic responsible for user creation.

Handler code looks like this:  

Please note that the class inherits from SimpleCommandHandler provided by Broadway. Thanks to that, you don’t have to call it – Broadway will do it for you. The only thing you have to do is to provide a proper method name (format: ‘handle’ + command name).

See also: Separating business logic in PHP

To create a user object, you need to use the factory method. It’ll create a domain object basing on the provided parameters. Of course, you save only a hash for the password, so the password needs to be encoded before passing through. The encoder is injected as a dependency to the handler. The last thing you have to do is to save a user using a repository which also has been injected as a dependency.


An event code looks like the one on an example below.

The object above informs you that the user has been created. It also contains its details. Here, you have another Broadway requirement – implementation of serialization/deserialization of an event. You have to do it on your own. The rest (save/read of the Event Store event) is done by Broadway.

User Aggregate Root

Aggregate Root objects have to extend a class  EventSourcedAggregateRoot.Thanks to that you get the possibility to apply events and to reconstitute objects from database.

Moreover, these objects have to meet a few additional requirements. First of all – you have to make sure that your object has its identifier. That’s why you have to implement getAggregateRootId() method.

Another requirement is to implement methods which are applying the proper event. Again, you have to provide a proper method name (format: ‘handle’ + event name).

See also: Switching framework and database tools in PHP

Please note that in a constructor, you can’t set any properties. You have to create a proper event, then it’ll be processed through the method applyUserWasCreatedEvent(). This solution enables applying the events to the object whilst recreating it from the Event Store. In the listing below, I purposely skipped accessors for private properties because I didn’t want to complicate the presented code. But obviously, they are needed in the final solution.


To fetch and save the data in the Event Store, you have to create a proper repository (EventSourcingRepository) which you can use in your class.

EventSourcingRepository requires you to provide a few arguments:

  • Event Store object,
  • Event Bus object,
  • a name of the class which will be operated (in the presented case it’s User),
  • a class of the object factory; I chose NamedConstructorAggregateFactory, which means the use of User class factory method instantiateForReconstitution(); then all the events will be applied,
  • eventStreamDecorators – an array of decorators which allow modifying events before saving them in the Event Store. You can add the metadata this way.

Additionally, I’ve created two methods to fetch the objects from the repository and save them in the same place.

It’s presented on the listing below.

This is how I’ve implemented the Write Model. Thanks to the use of Broadway, you don’t have to think about propagating the events. They will be put on Event Bus any time when a new event is saved by the repository. There they can be read by the read part of the app and used for the Read Model updates.

In the second part of CQRS and Event Sourcing implementation in PHP, I’ve focused on the implementation of the Write Model with Broadway library. The next part of the article will be about the implementation of the Read Model.

You may also like

What do you want to achieve?

    You can upload a file (optional)

    Upload file

    File should be .pdf, .doc, .docx, .rtf, .jpg, .jpeg, .png format, max size 5 MB

    0 % of

    or contact us directly at [email protected]

    This site is protected by reCAPTCHA and the Google
    Privacy Policy and Terms of Service apply.


    Thank you!

    Your message has been sent. We’ll get back to you in 24 hours.

    Back to page

    We’ll get back to you in 24 hours

    to get to know each other and address your needs as quick as possible.


    We'll work together on possible scenarios

    for the software development strategy in sync with your goals.


    We’ll turn the strategy into an actionable plan

    and provide you with experienced development teams to execute it.

    Our work was featured in:

    Tech Crunch
    Business Insider

    Aplikujesz do

    The Software House

    Copied Tekst skopiowany!

    Nie zapomnij dodać klauzuli:

    Kopiuj do schowka

    Jakie będą kolejne kroki?


    Rozmowa telefoniczna

    Krótka rozmowa o twoim doświadczeniu,
    umiejętnościach i oczekiwaniach.

    Test task

    Zadanie testowe

    Praktyczne zadanie sprawdzające dokładnie
    poziom twoich umiejętności.


    Spotkanie w biurze

    Rozmowa w biurze The Software House,
    pozwalająca nam się lepiej poznać.

    Response 200

    Response 200

    Ostateczna odpowiedź i propozycja
    finansowa (w ciągu kilku dni od spotkania).