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

Eloquent Message Repository Laravel Package

surgio/eloquent-message-repository

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps to Begin

  1. Installation

    composer require surgio/eloquent-message-repository:^4.0
    
  2. Publish Migrations

    php artisan vendor:publish --provider="Surgio\EloquentMessageRepository\EventSauceServiceProvider" --tag="migrations"
    

    Run the migration:

    php artisan migrate
    
  3. Basic Setup in a Service Register the repository in your EventSauce configuration (e.g., in a service provider or DI container):

    use Surgio\EloquentMessageRepository\EloquentMessageRepository;
    use EventSauce\EventSourcing\MessageSerializer\ConstructingMessageSerializer;
    
    $messageRepository = new EloquentMessageRepository(new ConstructingMessageSerializer());
    
  4. First Use Case: Storing Events Pass the repository to an AggregateRootRepository (e.g., ConstructingAggregateRootRepository):

    use EventSauce\EventSourcing\AggregateRootRepository\ConstructingAggregateRootRepository;
    
    $aggregateRootRepository = new ConstructingAggregateRootRepository(
        YourAggregate::class,
        $messageRepository
    );
    

Implementation Patterns

Core Workflows

  1. Event Storage The repository automatically persists events to the messages table (created by the migration). Each event is stored with:

    • aggregate_id (UUID)
    • aggregate_type (class name)
    • event_name (FQCN of the event)
    • event_data (serialized payload)
    • event_metadata (optional metadata)
    • occurred_on (timestamp)
  2. Event Retrieval Fetch events for an aggregate using:

    $events = $messageRepository->getEventsFor(
        aggregateId: $aggregateId,
        aggregateType: YourAggregate::class
    );
    
  3. Integration with Laravel Services Bind the repository to the container in a service provider:

    $this->app->bind(
        EventSauce\EventSourcing\MessageRepository::class,
        fn($app) => new EloquentMessageRepository(
            new ConstructingMessageSerializer()
        )
    );
    
  4. Event Sauce Process Setup Configure a process with the repository:

    use EventSauce\EventSourcing\AggregateRootRepository\ConstructingAggregateRootRepository;
    use EventSauce\EventSourcing\ProcessManager\SynchronousProcessManager;
    
    $processManager = new SynchronousProcessManager(
        new ConstructingAggregateRootRepository(
            YourAggregate::class,
            $messageRepository
        )
    );
    

Advanced Patterns

  1. Custom Serialization Override the default ConstructingMessageSerializer for custom event serialization:

    $serializer = new YourCustomSerializer();
    $messageRepository = new EloquentMessageRepository($serializer);
    
  2. Query Scoping Extend the repository to add custom query scopes (e.g., for soft-deleted events):

    class CustomEloquentMessageRepository extends EloquentMessageRepository
    {
        public function scopeForProcess($query, string $processName)
        {
            return $query->where('process_name', $processName);
        }
    }
    
  3. Event Metadata Handling Attach metadata to events during dispatch:

    $event = new YourEvent($data);
    $event->setMetadata(['user_id' => auth()->id()]);
    
  4. Bulk Operations Use Laravel’s query builder for bulk inserts (e.g., during batch processing):

    DB::table('messages')->insert($events);
    

Gotchas and Tips

Pitfalls

  1. Migration Conflicts

    • If the messages table already exists, manually inspect the migration to avoid schema conflicts.
    • Ensure aggregate_id is a UUID-compatible column (e.g., uuid type in PostgreSQL or char(36) in MySQL).
  2. Serialization Issues

    • Events must implement EventSauce\EventSourcing\Message. Non-compliant events will throw exceptions.
    • Circular references in event payloads may cause serialization errors. Use #[Spatie\LaravelIgnition\Ignition] or similar tools to debug.
  3. Performance with Large Aggregates

    • Fetching all events for a long-lived aggregate may time out. Use pagination or lazy loading:
      $events = $messageRepository->getEventsFor($aggregateId, YourAggregate::class, 100, 0);
      
  4. Concurrency Control

    • The repository does not handle optimistic locking by default. Add a version column to the messages table if needed and implement checks in your aggregates.

Debugging Tips

  1. Query Logging Enable Laravel’s query logging to inspect SQL:

    DB::enableQueryLog();
    $messageRepository->getEventsFor($aggregateId, YourAggregate::class);
    dd(DB::getQueryLog());
    
  2. Event Validation Validate event data before dispatching:

    $event->validate(); // If using Laravel validation traits
    
  3. Repository Testing Mock the repository in tests to isolate aggregate logic:

    $mockRepo = Mockery::mock(EloquentMessageRepository::class);
    $mockRepo->shouldReceive('getEventsFor')
             ->andReturn([$event1, $event2]);
    

Extension Points

  1. Custom Event Table Override the table name in the repository constructor:

    $messageRepository = new EloquentMessageRepository(
        new ConstructingMessageSerializer(),
        'custom_event_table'
    );
    
  2. Event Filtering Extend the repository to filter events by metadata or other criteria:

    class FilteredEloquentMessageRepository extends EloquentMessageRepository
    {
        public function getEventsForWithMetadata($aggregateId, $aggregateType, $metadataKey, $metadataValue)
        {
            return $this->newQuery()
                ->where('aggregate_id', $aggregateId)
                ->where('aggregate_type', $aggregateType)
                ->whereJsonContains('event_metadata->>' . $metadataKey, $metadataValue)
                ->get();
        }
    }
    
  3. Event Sauce Middleware Integrate with EventSauce middleware for cross-cutting concerns (e.g., logging, auditing):

    use EventSauce\EventSourcing\Middleware\Middleware;
    
    $middleware = new YourMiddleware();
    $processManager = new SynchronousProcessManager(
        $aggregateRootRepository,
        [$middleware]
    );
    
  4. Laravel Events Dispatch Laravel events alongside EventSauce events for UI updates:

    event(new YourLaravelEvent($eventData));
    
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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky