@juguul
juliens@php.net
Lead développeur / Référent technique
Alptis Assurances
s.delicata@alptis.fr
Eric Evans (2003)
Vaughn Vernon (2013)
interface DomainEventInterface
{
public function getType();
public function getRootEntityId();
public function occurredOn();
public function getInformations();
}
$a = "STRING";
Exemple d'un domain event
class NomProduitChangedDomainEvent implements DomainEventInterface {
public function __construct($produitId, $ancienNom, $nouveauNom) {
$this->type = 'produit.nom.changed';
$this->rootEntityId = $produitId;
$this->occuredOn = new \DateTime();
$this->informations = [
'ancienNom' => $ancienNom,
'nouveauNom' => $nouveauNom
];
}
public function getType() { return $this->type; }
public function getRootEntityId() { return $this->rootEntityId; }
public function occurredOn() { return $this->occuredOn; }
public function getInformations() { return $this->informations; }
}
Dispatch depuis le stock
namespace Stock\Entity;
class Produit {
private $nom;
public function changeNom($nouveauNom) {
$ancienNom = $this->nom;
$this->nom = $nouveauNom;
$this->dispatch(new NomProduitChangedDomainEvent(
$this->getId(),
$ancienNom,
$nouveauNom
));
}
}
Listener de l'e-boutique
namespace Eboutique\Listener;
class NomProduitChangedListener {
public function __construct(EntityRepository $repository) {
$this->repository = $repository;
}
public function handle(NomProduitChangedDomainEvent $event) {
// Met à jour l'entité Produit du Bounded Context E-boutique
$informations = $event->getInformations();
$produit = $this->repository->get($event->getRootEntityId());
$produit->changeNom($informations['nouveauNom']);
$this->repository->save($produit);
}
}
J'ai pas mis de chat, mais j'ai mis un lapin ca compte ?
Stocker toutes les modifications du système, plutôt que seulement son état actuel
Heu... Oui, mais du coup c'est quoi le rapport avec les Domain Events ?
[
{
"_id":"a2ef4d345bf",
"type":"adresse.changed",
"entity_id": 5,
"occurredOn": { "date": "2016-10-11 09:04:31.000000" },
"nouvelle_adresse":"31 rue de la conf 69008 LYON"
},
{
"_id":"bce462bb567",
"type":"sexe.changed" // WTF ?
"entity_id": 1,
"occurredOn": { "date": "2016-10-09 09:00:31.000000" },
"ancien_sexe": "F",
"nouveau_sexe": "M"
}
]
//Atention il faut qu'il soit synchrone
class DomainEventPersistanceListener {
public function persistEvent(DomainEvent $domainEvent) {
$this->repository->save($domainEvent);
}
}
class EventRepository {
public function findEvents($offset = false, $limit = false)
{
$results = $this->connection->db->events->find()->sort(array('occurredOn' => 1));
$results->skip($offset);
$results->limit($limit);
return array_reverse($results);
}
}
/** @Route("/events") */
public function lastEventsAction() {
$last_page = $this->get('events_repository')->getLastPageNumber();
$arResponse = [ 'events'=> $this->get('events_repo')->getLastEvents() ];
if ($last_page>1) {
$arResponse['previous_page'] = $last_page-1;
}
return new JsonResponse($arResponse);
}
/** @Route("/events/{page}") */
public function EventsAction($page) {
$last_page = $this->get('events_repository')->getLastPageNumber();
$arResponse = [ 'events'=>
$this->get('events_repo')->getEventsByPage($page) ]
if ($last_page>1) {
$arResponse['previous_page'] = $last_page-1;
}
if ($page<$last_page) {
$arResponse['next_page'] = $last_page+1;
}
$response = new JsonResponse($arResponse);
$response->setMaxAge(31536000);
return $response;
}
//extrait de handle()
$eventToDispatch = [];
foreach ($this->getEvents() as $event) {
if ($event['id']==$last_id) {
break;
}
$eventsToDispatch[] = $event
}
foreach(array_reverse($eventsToDispatch) as $event) {
$this->dispatcher->dispatch($event);
}
public function getEvents() {
$events_api = json_decode(file_get_contents($url.'/events'));
do {
foreach($events_api['events'] as $event) {
yield $event;
}
if (!isset($events_api['previous_page'])) {
$events_api = false;
} else {
$events_api = json_decode(file_get_contents($events_api['previous_page']);
}
} while($events_api!==false);
}
namespace Eboutique\Listener;
class NomProduitChangedListener {
public function __construct(EntityRepository $repository) {
$this->repository = $repository;
}
public function handle(NomProduitChangedDomainEvent $event) {
// Met à jour l'entité Produit du Bounded Context E-boutique
$informations = $event->getEventInformations();
$produit = $this->repository->get($event->getRootEntityId());
$produit->changeNom($informations['nouveauNom']);
$this->repository->save($produit);
}
}