} /** * @param RecordsEvents $aggregate * @return void */ public function add(RecordsEvents $aggregate) { // To store the updates made to an Aggregate, we only need to commit the latest recorded events to the `EventStore`. $events = $aggregate->getRecordedEvents(); $this->eventStore->commit($events); $aggregate->clearRecordedEvents(); } /** * @param IdentifiesAggregate $aggregateId * @return Basket */ public function get(IdentifiesAggregate $aggregateId) { // Fetching a single `Basket` is extremely easy: all we need is to reconstitute it from its history! Compare // that to the complexity of traditional ORMs. $aggregateHistory = $this->eventStore->getAggregateHistoryFor($aggregateId); return Basketv4::reconstituteFrom($aggregateHistory); } } $basketId = BasketId::generate(); $basket = BasketV4::pickUp($basketId); $basket->addProduct(ProductId::fromString('TPB01'), "The Princess Bride"); $baskets = new BasketRepository(new InMemoryEventStore()); $baskets->add($basket); $reconstitutedBasket = $baskets->get($basketId); it('should reconstitute a Basket to its state after persisting it', $basket == $reconstitutedBasket);
<?php // Domain Events describe things that have happened, but where do they come from? Wouldn't it be nice if we could make // the objects themselves responsible for recording whatever happened to them? We can, by implementing the // `RecordsEvents` interface. namespace Buttercup\Protects\Tests; use Buttercup\Protects\DomainEvent; use Buttercup\Protects\DomainEvents; use Buttercup\Protects\RecordsEvents; use Buttercup\Protects\Tests\Misc\ProductId; // Being good TDD'ers, let's write our tests first. $test = function () { // We pick up a Basket, add a product, and remove the product again. $basket = Basket::pickUp(BasketId::generate()); $basket->addProduct(new ProductId('TPB123'), "The Princess Bride"); $basket->removeProduct(new ProductId('TPB123')); // We'll want the recorded events to reflect that these three operations have happened. $events = $basket->getRecordedEvents(); it("should have recorded 3 events", 3 == count($events)); it("should have a BasketWasPickedUp event", $events[0] instanceof BasketWasPickedUp); it("should have a ProductWasAddedToBasket event", $events[1] instanceof ProductWasAddedToBasket); it("should have a ProductWasRemovedFromBasket event", $events[2] instanceof ProductWasRemovedFromBasket); // We'll want a way to clear the events, so that the next time we call a method on Basket, we don't get a list with // old and new events mixed in the same result. $basket->clearRecordedEvents(); it("should have no more events after clearing it", 0 == count($basket->getRecordedEvents())); }; // We'll implement the simplest Basket we can to satisfy the tests. By ignoring the PHP syntax, you can read the class // definition as **natural language**: // > A basket records events.