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

Messenger Laravel Package

cv65kr/messenger

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup for Laravel

Since this package is Symfony-focused, Laravel integration requires adaptation (no native support). Start by:

  1. Install via Composer (Symfony dependencies may conflict; use symfony/messenger as a base):

    composer require cv65kr/messenger symfony/messenger
    
  2. Publish Configs (adapt for Laravel):

    php artisan vendor:publish --provider="Messenger\MessengerBundle\MessengerBundle" --tag="config"
    
    • Modify config/messenger.php to match Laravel’s queue system (e.g., sync/async transports).
  3. Database Setup:

    • Run migrations manually (no Laravel Artisan support):
      php artisan migrate --path=/vendor/cv65kr/messenger/migrations
      
    • Or create a custom Laravel migration copying the schema from the package’s EventStore table.
  4. First Use Case:

    • Define an Aggregate Root (e.g., User) extending AggregateRoot (adapt for Laravel’s PSR-4 autoloading).
    • Example:
      namespace App\Domain\User;
      
      use Messenger\EventSourcing\AggregateRoot;
      use Messenger\EventSourcing\EventInterface;
      
      class User extends AggregateRoot
      {
          public static function create(string $email): self
          {
              $user = new self();
              $user->recordThat(new UserCreated($email)); // Custom event
              return $user;
          }
      }
      

Implementation Patterns

Core Workflows

  1. Event Sourcing:

    • Recording Events: Use recordThat() or apply() in aggregates to persist state changes as events.
      $user->recordThat(new EmailChanged($newEmail));
      
    • Replaying Events: Load aggregates from the event store:
      $user = User::fromHistory($userId, $eventStore);
      
  2. CQRS Separation:

    • Commands: Dispatch via Laravel’s bus (e.g., Bus::dispatch(new RegisterUser($email))).
    • Queries: Use Laravel’s Eloquent or custom repositories for read models.
      // Example: Query service
      $user = app(UserReadModel::class)->findByEmail($email);
      
  3. Messenger Integration:

    • Route commands/events to Laravel queues:
      // config/messenger.php
      'transports' => [
          'async' => [
              'dsn' => 'sync://default', // Use Laravel's queue:work
          ],
      ],
      
  4. Domain Events:

    • Publish events after commands:
      event(new UserRegistered($userId));
      // Or via Messenger:
      $bus->dispatch(new PublishDomainEvent($event));
      

Laravel-Specific Tips

  • Service Providers: Bind interfaces to implementations in AppServiceProvider:
    $this->app->bind(
        EventStoreInterface::class,
        fn($app) => new LaravelEventStore($app['db'])
    );
    
  • Console Commands: Extend Symfony’s EventStoreCommand for Laravel:
    php artisan event:replay UserCreated --from=2023-01-01
    

Gotchas and Tips

Pitfalls

  1. Symfony Dependencies:

    • Conflicts with Laravel’s symfony/console or symfony/dependency-injection. Use replace in composer.json:
      "replace": {
          "symfony/console": "6.*",
          "symfony/dependency-injection": "6.*"
      }
      
  2. Event Store Schema:

    • The package assumes a specific event_store table. Migrate manually or extend the EventStore class to use Laravel’s migrations.
  3. Async Bus:

    • The Symfony messenger.yaml config won’t work directly. Use Laravel’s queue system:
      // config/messenger.php
      'routing' => [
          'App\Command\*' => 'async',
      ],
      
  4. Aggregate Loading:

    • AggregateRoot::fromHistory() requires a custom EventStore implementation. Example:
      class LaravelEventStore implements EventStoreInterface
      {
          public function load(string $aggregateId): array
          {
              return Event::where('aggregate_id', $aggregateId)
                          ->orderBy('occurred_on')
                          ->get()
                          ->toArray();
          }
      }
      

Debugging

  • Event Replay Issues:

    • Verify event classes implement EventInterface and are serializable (use Symfony\Component\Serializer\Annotation\SerializedName).
    • Check occurred_on timestamps in the event store for chronological order.
  • Command Handling:

    • Use Laravel’s HandleFails middleware to catch unhandled commands:
      $bus->subscribeToCommand(RegisterUser::class, RegisterUserHandler::class)
          ->handleFails(fn($command, $exception) => Log::error($exception));
      

Extension Points

  1. Custom Event Stores:

    • Extend EventStoreInterface for databases like PostgreSQL (JSONB) or Redis.
  2. Projection Handlers:

    • Adapt Symfony’s Projection to Laravel’s event listeners:
      Event::listen(UserRegistered::class, function ($event) {
          UserReadModel::sync($event->userId, $event->email);
      });
      
  3. Testing:

    • Mock the EventStore and Bus interfaces:
      $eventStore = Mockery::mock(EventStoreInterface::class);
      $eventStore->shouldReceive('save')->once();
      
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