Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Event Store Symfony Bundle Laravel Package

prooph/event-store-symfony-bundle

Deep Wiki
Context7

Getting Started

Minimal Setup

  1. 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],
    ];
    
  2. 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
    
  3. 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]);
        }
    }
    

Implementation Patterns

Event Sourcing Workflow

  1. 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]);
        }
    }
    
  2. 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
    
  3. 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;
        }
    }
    
  4. Event Bus Integration Use EventPublisher for synchronous publishing or EventBus for async:

    $this->eventPublisher->publish(new OrderCreated(...)); // Sync
    $this->eventBus->dispatch(new OrderCreated(...));     // Async
    

Gotchas and Tips

Common Pitfalls

  1. Stream Naming

    • Use UUIDs or domain-specific IDs (e.g., order-{uuid}) for streams to avoid collisions.
    • Avoid generic names like events or default.
  2. Projection Errors

    • Projections fail silently by default. Enable logging or use ProjectionRunning events to debug:
      prooph_event_store:
          projections:
              read_model:
                  projection_config:
                      logger: "@monolog.logger.event_store"
      
  3. Event Serialization

    • Ensure events implement JsonSerializable or use Prooph\EventSourcing\Serialization\Serializer:
      use Prooph\EventSourcing\Serialization\Serializer;
      
      $serializer = new Serializer();
      $serializedEvent = $serializer->serialize($event);
      
  4. Transaction Isolation

    • The bundle does not handle transactions by default. Use Symfony’s TransactionEventListener or Doctrine transactions:
      use Doctrine\ORM\EntityManagerInterface;
      
      $entityManager->transactional(function () use ($eventStore) {
          $eventStore->appendToStream(...);
      });
      

Debugging Tips

  1. Check Stream Existence Use the StreamMetadata class to verify streams:

    $metadata = $eventStore->getStreamMetadata($streamName);
    
  2. Inspect Events Dump events from a stream:

    $events = $eventStore->load($streamName, 0, 10);
    dd($events);
    
  3. CLI Commands

    • List streams: php bin/console prooph:event-store:list-streams
    • Show stream: php bin/console prooph:event-store:show-stream order-{uuid}

Extension Points

  1. 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 { /* ... */ }
    }
    
  2. Middleware for Events Add middleware to the EventBus:

    $eventBus->addMiddleware(new LoggingMiddleware());
    
  3. 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
        }
    }
    
  4. Symfony Messenger Bridge Use prooph/event-store-messenger-bundle to integrate with Symfony Messenger:

    composer require prooph/event-store-messenger-bundle
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
comsave/common
alecsammon/php-raml-parser
chrome-php/wrench
lendable/composer-license-checker
typhoon/reflection
mesilov/moneyphp-percentage
mike42/gfx-php
bookdown/themes
aura/view
aura/html
aura/cli
povils/phpmnd
nayjest/manipulator
omnipay/tests
psr-mock/http-message-implementation
psr-mock/http-factory-implementation
psr-mock/http-client-implementation
voku/email-check
voku/urlify
rtheunissen/guzzle-log-middleware