CQRS — это архитектурный паттерн, разделяющий операции чтения (Query) и записи (Command) в разные модели.
Разделение моделей:
Разные каналы:
// Command
class CreateUserHandler
{
public function __construct(private UserRepository $users) {}
public function handle(CreateUserCommand $command): void
{
$user = User::create($command->email, $command->password);
$this->users->save($user);
}
}
// Query
class UserListQueryHandler
{
public function __construct(private UserReadModel $readModel) {}
public function handle(UserListQuery $query): array
{
return $this->readModel->findAll($query->limit, $query->offset);
}
}
Хранение состояния системы как последовательности событий, а не текущего состояния.
class UserAggregate
{
private array $events = [];
public static function create(UserId $id, string $email): self
{
$user = new self();
$user->record(new UserCreated($id, $email));
return $user;
}
private function record(object $event): void
{
$this->events[] = $event;
}
public function getEvents(): array
{
return $this->events;
}
}
class EventStore
{
public function append(AggregateId $id, array $events): void
{
// Сохранение событий
}
}
class UserAggregateReconstructor
{
public function reconstruct(UserId $id, array $events): UserAggregate
{
$user = new UserAggregate();
foreach ($events as $event) {
$user->apply($event);
}
return $user;
}
}
Command Side:
Query Side:
// 1. Обработка команды
$command = new CreateUserCommand('test@example.com');
$handler->handle($command);
// 2. Генерация события
$events = $aggregate->getEvents();
$eventStore->append($userId, $events);
// 3. Обновление проекции
$projector->handleEvents($events);
CQRS и Event Sourcing — мощные паттерны для сложных систем. CQRS разделяет ответственность за чтение и запись, а Event Sourcing сохраняет историю изменений как последовательность событий. Вместе они обеспечивают масштабируемость, гибкость и надежность, но требуют более сложной архитектуры и подходят не для всех проектов.