Installation Add the bundle via Composer:
composer require prooph/event-store-symfony-bundle
Enable it in config/bundles.php:
return [
// ...
Prooph\EventStore\SymfonyBundle\ProophEventStoreBundle::class => ['all' => true],
];
Configuration
Define your event store in config/packages/prooph_event_store.yaml:
prooph_event_store:
stores:
default:
event_store: prooph_event_store.default
repository: prooph_event_store.default
projection_manager: prooph_event_store.default
First Use Case: Publishing an Event
Inject the EventStore and EventPublisher into a service:
use Prooph\EventStore\EventStore;
use Prooph\EventStoreBus\EventPublisher;
class OrderService
{
public function __construct(
private EventStore $eventStore,
private EventPublisher $eventPublisher
) {}
public function createOrder(Order $order)
{
$event = new OrderCreated($order->getId(), $order->getData());
$this->eventPublisher->publish($event);
$this->eventStore->appendToStream($order->getId(), [$event]);
}
}
Command Handling Use Symfony’s Messenger component to dispatch commands:
use Prooph\EventStoreBus\EventBus;
class OrderCommandHandler
{
public function __construct(
private EventBus $eventBus,
private EventStore $eventStore
) {}
public function __invoke(CreateOrderCommand $command)
{
$event = new OrderCreated($command->getId(), $command->getData());
$this->eventBus->dispatch($event);
$this->eventStore->appendToStream($command->getId(), [$event]);
}
}
Projection Management
Define projections in YAML (config/packages/prooph_event_store.yaml):
prooph_event_store:
projections:
read_model:
event_store: prooph_event_store.default
projection_name: "read_model_projection"
projection_class: App\Projection\ReadModelProjection
projection_config: { /* config */ }
Run projections via CLI:
php bin/console prooph:event-store:run-projections
Aggregate Root Pattern
Implement AggregateRoot interface for domain entities:
use Prooph\EventSourcing\AggregateRoot;
class Order implements AggregateRoot
{
private $recordedEvents = [];
public function apply(OrderCreated $event)
{
// Apply event to entity state
}
public function recordThat(OrderCreated $event)
{
$this->recordedEvents[] = $event;
$this->apply($event);
}
public function releaseEvents(): array
{
return $this->recordedEvents;
}
}
Event Bus Integration
Use EventPublisher for synchronous publishing or EventBus for async:
$this->eventPublisher->publish(new OrderCreated(...)); // Sync
$this->eventBus->dispatch(new OrderCreated(...)); // Async
Stream Naming
order-{uuid}) for streams to avoid collisions.events or default.Projection Errors
ProjectionRunning events to debug:
prooph_event_store:
projections:
read_model:
projection_config:
logger: "@monolog.logger.event_store"
Event Serialization
JsonSerializable or use Prooph\EventSourcing\Serialization\Serializer:
use Prooph\EventSourcing\Serialization\Serializer;
$serializer = new Serializer();
$serializedEvent = $serializer->serialize($event);
Transaction Isolation
TransactionEventListener or Doctrine transactions:
use Doctrine\ORM\EntityManagerInterface;
$entityManager->transactional(function () use ($eventStore) {
$eventStore->appendToStream(...);
});
Check Stream Existence
Use the StreamMetadata class to verify streams:
$metadata = $eventStore->getStreamMetadata($streamName);
Inspect Events Dump events from a stream:
$events = $eventStore->load($streamName, 0, 10);
dd($events);
CLI Commands
php bin/console prooph:event-store:list-streamsphp bin/console prooph:event-store:show-stream order-{uuid}Custom Event Store
Implement Prooph\EventStore\EventStoreInterface for non-DB backends (e.g., Kafka, Redis):
class CustomEventStore implements EventStoreInterface
{
public function appendToStream(...): void { /* ... */ }
public function load(...): array { /* ... */ }
}
Middleware for Events
Add middleware to the EventBus:
$eventBus->addMiddleware(new LoggingMiddleware());
Custom Projection Logic
Extend Prooph\EventStore\Projection\Projection for complex projections:
class CustomProjection extends Prooph\EventStore\Projection\Projection
{
protected function whenOrderCreated(OrderCreated $event): void
{
// Custom logic
}
}
Symfony Messenger Bridge
Use prooph/event-store-messenger-bundle to integrate with Symfony Messenger:
composer require prooph/event-store-messenger-bundle
How can I help you explore Laravel packages today?