Created
March 14, 2019 09:52
-
-
Save pwm/58e96d080e1482141bb0b550165efd14 to your computer and use it in GitHub Desktop.
S-Flow - Event sourcing example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
final class Order | |
{ | |
/** @var Event */ | |
private $events; | |
/** @var State */ | |
private $state; | |
public function __construct(Events $events) | |
{ | |
$this->events = $events; | |
$this->state = $this->buildState($events); | |
} | |
public function getEvents(): Events | |
{ | |
return $this->events; | |
} | |
public function getState(): State | |
{ | |
return $this->state; | |
} | |
private function buildState(Events $events): State | |
{ | |
$transitionOp = $this->fsm()->run(new S\NoItems, $events); | |
if ($transitionOp->isSuccess() === false) { | |
throw new RuntimeException( | |
sprintf( | |
'Invalid transition: from %s via %s', | |
$transitionOp->getState()::name()->unWrap(), | |
$transitionOp->getLastEvent()::name()->unWrap() | |
) | |
); | |
} | |
return $transitionOp->getState(); | |
} | |
private function fsm(): FSM | |
{ | |
$labels = [ | |
S\NoItems::name(), | |
S\HasItems::name(), | |
S\NoCard::name(), | |
S\CardSelected::name(), | |
S\CardConfirmed::name(), | |
S\OrderPlaced::name(), | |
]; | |
$arrows = [ | |
(new Arrow(E\Select::name()))->from(S\NoItems::name())->via(new T\AddFirstItem), | |
(new Arrow(E\Select::name()))->from(S\HasItems::name())->via(new T\AddItem), | |
(new Arrow(E\Checkout::name()))->from(S\HasItems::name())->via(new T\DoCheckout), | |
(new Arrow(E\SelectCard::name()))->from(S\NoCard::name())->via(new T\DoSelectCard), | |
(new Arrow(E\Confirm::name()))->from(S\CardSelected::name())->via(new T\ConfirmCard), | |
(new Arrow(E\PlaceOrder::name()))->from(S\CardConfirmed::name())->via(new T\DoPlaceOrder), | |
(new Arrow(E\Cancel::name()))->from(S\NoCard::name())->via(new T\DoCancel), | |
(new Arrow(E\Cancel::name()))->from(S\CardSelected::name())->via(new T\DoCancel), | |
(new Arrow(E\Cancel::name()))->from(S\CardConfirmed::name())->via(new T\DoCancel), | |
]; | |
return new FSM((new Graph(...$labels))->drawArrows(...$arrows)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
// Get the events (eg. from the DB) | |
$events = new Events( | |
new E\Select(new Item('foo')), | |
new E\Select(new Item('bar')), | |
new E\Select(new Item('baz')), | |
new E\Checkout, | |
new E\SelectCard(new Card('Visa', '1234567812345678')), | |
new E\Confirm, | |
new E\PlaceOrder | |
); | |
// Build the entity | |
$order = new Order($events); | |
\assert($order->getState() instanceof S\OrderPlaced); // true |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment