@return int */ public function open(); /** @return Account */ public function get($accountId); /** @return Account[] */ public function findAll($userId); /** @return void */ public function credit($accountId, $balance); /** @return void */ public function debit($accountId, $balance); }
/** @return Account[] */ public function findAll($userId); /** @return int */ public function open(); /** @return void */ public function credit($accountId, $balance); /** @return void */ public function debit($accountId, $balance); Should be void Queries
// ... public function debit(Money $balance) { if ($this-‐>amount < $balance-‐>getAmount()) { throw new NotEnoughMoneyException( 'Cannot debit more than current amount' ); } return $this-‐>apply(new AccountWasCredited( $this-‐>accountId, $balance-‐>getAmount(), $balance-‐>getCurrency() )); } }
in datastore Example Two debits of 100€ must not be accepted if only 100€ left Load aggregate from EventStore: 100€ Create AccountWasDebited(100) event Append event in datastore Event must NOT be appended twice
private $uncommittedEvents = array(); private $playhead = -‐1; /** * Applies an event. * The event is added to the list of uncommited events. */ public function apply($event) { $this-‐>playhead++; $this-‐>uncommittedEvents[] = DomainMessage::recordNow( $this-‐>getAggregateRootId(), $this-‐>playhead, new Metadata(array()), $event ); } }