Installation
composer require ano/cqrs-bundle
Register the bundle in config/bundles.php:
return [
// ...
Ano\CqrsBundle\AnoCqrsBundle::class => ['all' => true],
];
First Use Case: Command Handling
Define a command class (e.g., CreateUserCommand):
namespace App\Command;
use Ano\CqrsBundle\Command\Command;
class CreateUserCommand implements Command
{
public $name;
public $email;
}
Create a handler (e.g., CreateUserCommandHandler):
namespace App\Command\Handler;
use App\Command\CreateUserCommand;
use Ano\CqrsBundle\Command\CommandHandler;
class CreateUserCommandHandler implements CommandHandler
{
public function handle(CreateUserCommand $command)
{
// Business logic here
return new UserCreatedEvent($command->email);
}
}
Dispatching Commands
Inject the CommandBus into your controller/service:
use Ano\CqrsBundle\Command\CommandBus;
class UserController
{
public function __construct(private CommandBus $commandBus) {}
public function createUser()
{
$command = new CreateUserCommand();
$command->name = 'John Doe';
$command->email = 'john@example.com';
$this->commandBus->dispatch($command);
}
}
CreateUserCommand, UpdateUserCommand).GetUserQuery). Note: The bundle relies on beberlei/lite-cqrs, which primarily focuses on commands.Leverage events for auditing or side effects:
// In handler:
return new UserCreatedEvent($command->email);
// Subscribe to events:
use Ano\CqrsBundle\Event\EventSubscriber;
class UserCreatedEventSubscriber implements EventSubscriber
{
public static function getSubscribedEvents()
{
return [
'user.created' => 'onUserCreated',
];
}
public function onUserCreated(UserCreatedEvent $event)
{
// Side effects (e.g., send welcome email)
}
}
Add pre/post-processing logic:
use Ano\CqrsBundle\Command\CommandMiddleware;
class LoggingMiddleware implements CommandMiddleware
{
public function handle($command, callable $next)
{
\Log::info('Command dispatched:', ['command' => get_class($command)]);
return $next($command);
}
}
Register middleware in config/packages/ano_cqrs.yaml:
ano_cqrs:
command_bus:
middlewares:
- App\Middleware\LoggingMiddleware
Use repositories for data access (integrate with Doctrine or custom implementations):
use Ano\CqrsBundle\Repository\Repository;
class UserRepository implements Repository
{
public function save(User $user) { /* ... */ }
public function findByEmail(string $email) { /* ... */ }
}
No Built-in Query Support
The bundle focuses on commands. For queries, consider pairing with beberlei/doctrine-orm-query-builder or a custom solution.
Event Dispatching
Events are not automatically dispatched by the bundle. Use beberlei/lite-cqrs's EventBus or Symfony’s EventDispatcher for event handling.
Middleware Order Matters Middlewares are executed in the order they are registered. Place validation middleware early, logging middleware late.
Dependency Injection
Ensure handlers are properly tagged as services in services.yaml:
services:
App\Command\Handler\CreateUserCommandHandler:
tags: ['ano_cqrs.command_handler']
Command Not Found?
Verify the handler is tagged as a service and implements CommandHandler. Check ano_cqrs.yaml for misconfigurations.
Events Not Triggered?
Confirm the event class is properly dispatched (e.g., via EventBus or Symfony’s EventDispatcher).
Custom Command Bus
Extend Ano\CqrsBundle\Command\CommandBus to add retry logic or async processing.
Validation Integrate with Symfony Validator:
use Symfony\Component\Validator\Validator\ValidatorInterface;
class ValidationMiddleware implements CommandMiddleware
{
public function __construct(private ValidatorInterface $validator) {}
public function handle($command, callable $next)
{
$errors = $this->validator->validate($command);
if (count($errors)) {
throw new \RuntimeException('Validation failed');
}
return $next($command);
}
}
Testing
Mock the CommandBus in unit tests:
$commandBus = $this->createMock(CommandBus::class);
$commandBus->expects($this->once())->method('dispatch');
Bundle Prefix
The bundle uses ano_cqrs as the configuration key. Ensure YAML files reflect this (e.g., config/packages/ano_cqrs.yaml).
Doctrine Integration
If using Doctrine, configure repositories in ano_cqrs.yaml:
ano_cqrs:
repositories:
App\Entity\User: App\Repository\UserRepository
How can I help you explore Laravel packages today?