ddd.io

Broadway is an excellent project that brings CQRS (Command Query Responsibility Segregation) and Event Sourcing to PHP projects. While the examples for Aggregate Roots are relatively easy to follow figuring out how to handle child Entities was a little more tricky.

I ran into this pretty early with my first Broadway domain model implementation. The domain model suggested that I needed to work with child Entities but it was not clear where the best place was to instantiate them. The second issue was figuring out exactly how the Events flowed through the components of the Aggregate Root.

My initial hope was that EventSourcedEntity classes would be consistent with how I was building EventSourcedAggregateRoot classes. The pattern I was using for Aggregate Roots was to use named constructors and emit "creation events."

After much trial, error, and a few chats with the Broadway team in #qandidate on Freenode, it became clear that child Entities should not emit their own "creation events."

The reason for this was a chicken or the egg problem.

If the child Entity was created in a normal method on the Aggregate Root (not one of the apply* methods) it would work fine during normal execution and the proper Event Stream was created. However, upon reconstitution, the child Entity instance was never created since none of the apply* methods instantiated the instance.

If the child Entity was created in an apply* method of an Aggregate Root it would work fine during normal execution and the proper Event Stream was created. However, upon each reconstitution, an additional instance of the Entity would be created every time since the Event that created the child Entity would result in calling the named constructor in the child Entity. This named constructor would, of course, emit another creation Event.

This seemed obvious after the fact, but having the child Entity emit "creation events" was never going to work. I struggled against leaving this pattern because I very much wanted my child Entities to look and behave just like my Aggregate Roots. You know, because consistency! In the end, I gave in and decided to roll with KISS over Consistency.

Rather than emitting an Event to specifically trigger the creation of the child Entity we need to instantiate the child Entity in the Aggregate Root itself. We can still use a named constructor but the instantiation of the object should not result in additional Events being emitted from the child Entity.

To illustrate this, let's consider a contrived domain model around manufactured parts. In our domain model, a Part is manufactured by a Manufacturer. The Manufacturer of a Part cannot be changed once the Part is manufactured. However, the name of the Manufacturer may change.

How would we model both Part, Manufacturer, and changing the Manufacturer's name? Let's start with the Aggregate Root.

use Broadway\EventSourcing\EventSourcedAggregateRoot;

class Part extends EventSourcedAggregateRoot
{
    private $partId;
    private $manufacturer;

    public static function manufacture($partId, $manufacturerId, $manufacturerName)
    {
        $part = new Part();

        $part->apply(new PartWasManufacturedEvent(
            $partId,
            $manufacturerId,
            $manufacturerName
        ));

        return $part;
    }

    public function applyPartWasManufacturedEvent(PartWasManufacturedEvent $event)
    {
        $this->partId = $event->partId;

        $this->manufacturer = new Manufacturer(
            $event->partId,
            $event->manufacturerId,
            $event->manufacturerName
        );
    }

This is standard fare with Broadway. The main thing to notice here is that we are simply instantiating an instance of our Entity in an apply* method.

The last piece of the puzzle on the Aggregate Root side of things is to let Broadway know about the Aggregate Root's child Entities. This is done by overriding the getChildEntities method for an Aggregate Root. This method is expected to return all of the child Entity instances that the Aggregate Root knows about. The default implementation is to return an empty array.

class Part extends EventSourcedAggregateRoot
{
    private $manufacturer;

    protected function getChildEntities()
    {
        return [$this->manufacturer];
    }
}

It is important to note that the Aggregate Root itself will always handle each event itself before getChildEntities is called.

In this example, we know that the first Event in the Event Stream is always going to be PartWasManufacturedEvent and manufacturer is set in applyPartWasManufacturedEvent. This means that we can safely assume that manufacturer will always be instantiated by the first time getChildEntities is called.

Care should be taken to ensure that only instantiated and valid Entities are returned from this method.

The following is an example of a Broadway child Entity. Here we have a typical public constructor and a rename method that emits an Event.

use Broadway\EventSourcing\EventSourcedEntity;

class Manufacturer extends EventSourcedEntity
{
    private $partId;
    private $manufacturerId;
    private $manufacturerName;

    public function __construct($partId, $manufacturerId, $manufacturerName)
    {
        $this->partId = $partId;
        $this->manufacturerId = $manufacturerId;
        $this->manufacturerName = $manufacturerName;
    }

    public function rename($manufacturerName)
    {
        if ($this->manufacturerName === $manufacturerName) {
            // If the name is not actually different we do not need to do
            // anything here.
            return;
        }

        // This event may also be handled by the aggregate root.
        $this->apply(new PartManufacturerWasRenamedEvent(
            $this->partId,
            $manufacturerName
        ));
    }

    protected function applyPartManufacturerWasRenamedEvent(
        PartManufacturerWasRenamedEvent $event
    ) {
        $this->manufacturerName = $event->manufacturerName;
    }
}

Child Entities can emit Events and following the apply* conventions just like an Aggregate Root.

It is important to note, however, that behind the scenes Broadway is actually sending the event to the Aggregate Root first. The Aggregate Root will try to apply the Event to itself before sending the Event to each of its child Entities.

From here we can continue to add additional methods to both our Aggregate Root and our child Entity and both will be reconstituted from an Event Stream just fine!


While Broadway has a heavy focus on Aggregate Roots it provides great support for integration child Entities into your domain model implementation. Adding an Event Sourced child Entity to an Event Sourced Aggregate Root using Broadway isn’t so bad once you get a few concepts squared away.

Also, it doesn’t hurt to have a an example to look at. Fortunately, there is one now! To see this example in action, check out the example code shipped with Broadway. Since it was written in tandem with this post so it should seem pretty familiar.


If you are interested in CQRS / Event Sourcing in PHP and you haven't checked out Broadway yet, go do it now! Want to get involved? One great way would be to join the #qandidate IRC channel on Freenode. If you stop in, make sure to say "hi!" to simensen. Also, Qandidate.com is hiring! They are a great company creating great software and are actively contributing to the open-source community!

dflydev is available for consulting on Broadway and CQRS / Event Sourcing projects. We've contributed to Broadway core and have integrated Broadway into multiple projects since it was announced. Visit our services to learn more about how we can help your business and contact us to tell us more about your needs.