becklyn/ddd-core
DDD/CQRS/event-sourcing core building blocks for PHP: entity identities, domain events, command handling, transactions, and an event store workflow. Framework-agnostic abstractions with Symfony/Doctrine/SimpleBus bridge packages available.
Strengths:
CommandBus, EventStore, TransactionManager) allow integration with any stack (Laravel, Symfony, or custom implementations).Weaknesses:
Laravel Compatibility:
EventBus, but SimpleBus (Symfony’s default) would require a Laravel-compatible alternative (e.g., spatie/laravel-simple-bus).TransactionManager, but distributed transactions (e.g., across services) would need Saga orchestration (e.g., camspiers/laravel-queue-sagas).AggregateId, but UUIDs (recommended) may conflict with Laravel’s default incrementing IDs.Key Integration Points:
| Component | Laravel Equivalent | Customization Required |
|---|---|---|
| Command Bus | HTTP routes / Artisan commands | Middleware for correlation IDs |
| Event Bus | Laravel Events | Replace SimpleBus with Laravel-compatible pub/sub |
| Transaction Manager | DB Transactions | Wrap in TransactionManager |
| Event Store | Custom (DB/NoSQL) | Implement EventStore interface |
| Aggregate Repository | Eloquent Repositories | Extend AggregateRepository trait |
High Risks:
TransactionManager’s explicit rollback/commit.Prophecy may not align with Laravel’s PHPUnit conventions.Mitigation Strategies:
Order) before full adoption.becklyn/ddd-core for complex aggregates.EventStore).Laravel-Specific Considerations:
CommandBus.Route::post('/orders/{id}/cancel', function (CancelOrderCommand $command) {
$commandBus->dispatch($command);
return response()->json(['status' => 'queued']);
});
X-Correlation-ID headers into commands.SimpleBus with Laravel Events or a message queue (e.g., Redis, RabbitMQ).Event::listen(OrderCancelled::class, function (OrderCancelled $event) {
// Dispatch to another service or update projections
});
DB::transaction() in TransactionManager:
DB::transaction(function () use ($command, $transactionManager) {
$handler = new CancelOrderHandler($eventRegistry, $transactionManager);
$handler->handleCommand($command);
});
json column with EventStore interface.filesystem or a NoSQL database (e.g., DynamoDB).Eloquent repositories to implement AggregateRepository:
class OrderRepository implements AggregateRepository {
public function load(AggregateId $id): ?AggregateRoot {
return Order::find($id->value());
}
}
Symfony vs. Laravel Tradeoffs:
| Feature | Symfony Bridge Available | Laravel Workaround Needed |
|---|---|---|
| Command Bus | Yes (SimpleBus) | Custom middleware or queue-based dispatch |
| Event Bus | Yes (SimpleBus) | Laravel Events or queue listener |
| Transaction Manager | Yes (Doctrine) | Wrap Laravel DB transactions |
| Event Store | Yes (Doctrine) | Custom implementation (DB/NoSQL) |
| Testing Traits | Yes | Adapt PHPUnit/Prophecy to Laravel’s testing |
Order).Order as an aggregate with EventSourcedProviderCapabilities.CancelOrderCommand and handler.event_store with aggregate_id, event_type, payload).Order::replayEvents()).How can I help you explore Laravel packages today?