Since this package is Symfony-focused, Laravel integration requires adaptation (no native support). Start by:
Install via Composer (Symfony dependencies may conflict; use symfony/messenger as a base):
composer require cv65kr/messenger symfony/messenger
Publish Configs (adapt for Laravel):
php artisan vendor:publish --provider="Messenger\MessengerBundle\MessengerBundle" --tag="config"
config/messenger.php to match Laravel’s queue system (e.g., sync/async transports).Database Setup:
php artisan migrate --path=/vendor/cv65kr/messenger/migrations
EventStore table.First Use Case:
User) extending AggregateRoot (adapt for Laravel’s PSR-4 autoloading).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;
}
}
Event Sourcing:
recordThat() or apply() in aggregates to persist state changes as events.
$user->recordThat(new EmailChanged($newEmail));
$user = User::fromHistory($userId, $eventStore);
CQRS Separation:
Bus::dispatch(new RegisterUser($email))).// Example: Query service
$user = app(UserReadModel::class)->findByEmail($email);
Messenger Integration:
// config/messenger.php
'transports' => [
'async' => [
'dsn' => 'sync://default', // Use Laravel's queue:work
],
],
Domain Events:
event(new UserRegistered($userId));
// Or via Messenger:
$bus->dispatch(new PublishDomainEvent($event));
AppServiceProvider:
$this->app->bind(
EventStoreInterface::class,
fn($app) => new LaravelEventStore($app['db'])
);
EventStoreCommand for Laravel:
php artisan event:replay UserCreated --from=2023-01-01
Symfony Dependencies:
symfony/console or symfony/dependency-injection. Use replace in composer.json:
"replace": {
"symfony/console": "6.*",
"symfony/dependency-injection": "6.*"
}
Event Store Schema:
event_store table. Migrate manually or extend the EventStore class to use Laravel’s migrations.Async Bus:
messenger.yaml config won’t work directly. Use Laravel’s queue system:
// config/messenger.php
'routing' => [
'App\Command\*' => 'async',
],
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();
}
}
Event Replay Issues:
EventInterface and are serializable (use Symfony\Component\Serializer\Annotation\SerializedName).occurred_on timestamps in the event store for chronological order.Command Handling:
HandleFails middleware to catch unhandled commands:
$bus->subscribeToCommand(RegisterUser::class, RegisterUserHandler::class)
->handleFails(fn($command, $exception) => Log::error($exception));
Custom Event Stores:
EventStoreInterface for databases like PostgreSQL (JSONB) or Redis.Projection Handlers:
Projection to Laravel’s event listeners:
Event::listen(UserRegistered::class, function ($event) {
UserReadModel::sync($event->userId, $event->email);
});
Testing:
EventStore and Bus interfaces:
$eventStore = Mockery::mock(EventStoreInterface::class);
$eventStore->shouldReceive('save')->once();
How can I help you explore Laravel packages today?