syeedalireza/laravel-eventsource

Enterprise-grade Event Sourcing and CQRS implementation for Laravel. Build scalable, auditable applications with complete event history and temporal queries.

Installs: 0

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

pkg:composer/syeedalireza/laravel-eventsource

v1.0.0 2026-01-30 18:09 UTC

This package is not auto-updated.

Last update: 2026-01-30 18:15:37 UTC


README

Latest Version on Packagist Total Downloads GitHub Tests Action Status GitHub Code Style Action Status License

Enterprise-grade Event Sourcing and CQRS implementation for Laravel.

Build scalable, auditable applications with complete event history, temporal queries, and event-driven architecture. This package provides a production-ready implementation of Event Sourcing patterns with full CQRS support, projections, and snapshots.

๐Ÿš€ Features

  • Complete Event Store: Persist all domain events with full replay capability
  • CQRS Pattern: Separate command and query responsibilities
  • Aggregate Root: Build aggregates that maintain consistency boundaries
  • Projections: Build read models from event streams
  • Snapshots: Optimize aggregate reconstruction with automatic snapshots
  • Temporal Queries: Query your data at any point in time
  • Multiple Storage Drivers: PostgreSQL, MySQL, MongoDB support
  • Event Versioning: Handle event schema evolution gracefully
  • Async Projections: Process events asynchronously with Laravel Queue
  • Event Replay: Rebuild projections from scratch
  • Testing Helpers: Comprehensive testing utilities

๐Ÿ“‹ Requirements

  • PHP 8.1 or higher
  • Laravel 10.0 or higher
  • PostgreSQL 12+ / MySQL 8.0+ / MongoDB 5.0+

๐Ÿ“ฆ Installation

You can install the package via composer:

composer require syeedalireza/laravel-eventsource

Publish the configuration file:

php artisan vendor:publish --tag=eventsource-config

Run the migrations:

php artisan migrate

๐ŸŽฏ Quick Start

1. Define Your Events

use Syeedalireza\LaravelEventSource\Events\DomainEvent;

class AccountCreated extends DomainEvent
{
    public function __construct(
        public readonly string $accountId,
        public readonly string $ownerName,
        public readonly float $initialBalance
    ) {
        parent::__construct();
    }
}

2. Create an Aggregate

use Syeedalireza\LaravelEventSource\Aggregate\AggregateRoot;

class Account extends AggregateRoot
{
    private string $ownerName;
    private float $balance;

    public static function create(string $accountId, string $ownerName, float $initialBalance): self
    {
        $account = new self($accountId);
        $account->recordThat(new AccountCreated($accountId, $ownerName, $initialBalance));
        
        return $account;
    }

    protected function applyAccountCreated(AccountCreated $event): void
    {
        $this->ownerName = $event->ownerName;
        $this->balance = $event->initialBalance;
    }

    public function deposit(float $amount): void
    {
        $this->recordThat(new MoneyDeposited($this->aggregateId, $amount));
    }

    protected function applyMoneyDeposited(MoneyDeposited $event): void
    {
        $this->balance += $event->amount;
    }
}

3. Use the Event Store

use Syeedalireza\LaravelEventSource\Facades\EventStore;

// Create and save an aggregate
$account = Account::create('acc-123', 'John Doe', 1000.0);
$account->deposit(500.0);

EventStore::save($account);

// Load an aggregate
$account = EventStore::load(Account::class, 'acc-123');

// Get event stream
$events = EventStore::getStream('acc-123');

4. Create a Projection

use Syeedalireza\LaravelEventSource\Projections\Projector;

class AccountBalanceProjector extends Projector
{
    protected array $handles = [
        AccountCreated::class,
        MoneyDeposited::class,
        MoneyWithdrawn::class,
    ];

    public function onAccountCreated(AccountCreated $event): void
    {
        DB::table('account_balances')->insert([
            'account_id' => $event->accountId,
            'owner_name' => $event->ownerName,
            'balance' => $event->initialBalance,
            'created_at' => $event->occurredAt,
        ]);
    }

    public function onMoneyDeposited(MoneyDeposited $event): void
    {
        DB::table('account_balances')
            ->where('account_id', $event->accountId)
            ->increment('balance', $event->amount);
    }
}

๐Ÿ“– Advanced Usage

Snapshots

Enable automatic snapshots for faster aggregate reconstruction:

use Syeedalireza\LaravelEventSource\Contracts\Snapshotable;

class Account extends AggregateRoot implements Snapshotable
{
    public function createSnapshot(): array
    {
        return [
            'owner_name' => $this->ownerName,
            'balance' => $this->balance,
        ];
    }

    public static function restoreFromSnapshot(string $aggregateId, array $state, int $version): self
    {
        $account = new self($aggregateId);
        $account->ownerName = $state['owner_name'];
        $account->balance = $state['balance'];
        $account->version = $version;
        
        return $account;
    }
}

Temporal Queries

Query your data at any point in time:

// Get account state at specific date
$account = EventStore::loadAtDate(Account::class, 'acc-123', '2024-01-15');

// Get account state at specific version
$account = EventStore::loadAtVersion(Account::class, 'acc-123', 10);

Event Versioning

Handle event schema evolution:

class AccountCreatedV2 extends DomainEvent
{
    public int $version = 2;

    // Upcaster for old events
    public static function upcast(array $eventData): array
    {
        if ($eventData['version'] === 1) {
            $eventData['currency'] = 'USD'; // Add new field
            $eventData['version'] = 2;
        }
        
        return $eventData;
    }
}

Async Projections

Process projections asynchronously:

// In config/eventsource.php
'projections' => [
    'mode' => 'async', // or 'sync'
],

// Your projection will automatically be queued

๐Ÿงช Testing

composer test

Run with coverage:

composer test-coverage

Static analysis:

composer analyse

Code formatting:

composer format

๐Ÿ“š Documentation

For complete documentation, visit https://syeedalireza.github.io/laravel-eventsource

๐Ÿ”ง Configuration

The configuration file config/eventsource.php allows you to customize:

  • Event store driver (PostgreSQL, MySQL, MongoDB)
  • Snapshot settings and frequency
  • Projection mode (sync/async)
  • Event serialization
  • And more...

๐Ÿค Contributing

Please see CONTRIBUTING.md for details.

๐Ÿ”’ Security

If you discover any security-related issues, please email your.email@example.com instead of using the issue tracker.

๐Ÿ“ License

The MIT License (MIT). Please see License File for more information.

๐Ÿ™ Credits

๐Ÿ“– Learn More