public function persist($aggregateRoot)
 {
     $aggregateRootId = $this->identifierExtractor->extract($aggregateRoot);
     $stream = new Stream(Stream\Id::fromString($aggregateRootId));
     // ensure that the sequence index is set to the latest item
     // TODO: we should actually use a StreamRepository to retrieve the existing stream and its index
     $this->eventStore->fetchEvents($stream);
     $events = $this->eventsHandler->extractUncommittedEvents($aggregateRoot);
     foreach ($events as $domainEvent) {
         $event = new Stream\Event(Stream\Event\Id::generate(), new Stream\Event\Payload($this->domainEventSerializer->toArray($domainEvent)), new \DateTimeImmutable(), new Metadata(['type' => get_class($domainEvent)]));
         $this->eventStore->persist($stream, [$event]);
         if ($this->emitter) {
             $this->emitter->emit($domainEvent);
         }
     }
 }
<?php

use PhpInPractice\EventStore\EventStore;
use PhpInPractice\EventStore\Storage\InMemory;
use PhpInPractice\EventStore\Stream;
use PhpInPractice\EventStore\Stream\Event;
require_once __DIR__ . '/../vendor/autoload.php';
$eventStore = new EventStore(new InMemory());
$stream = new Stream(Stream\Id::generate());
$eventStore->persist($stream, [new Event(Event\Id::generate(), new Event\Payload())]);
$eventStore->persist($stream, [new Event(Event\Id::generate(), new Event\Payload())]);
$events = $eventStore->fetchEvents($stream);
var_export($events);