Awesome-claude-code cqrs-knowledge

CQRS architecture knowledge base. Provides patterns, antipatterns, and PHP-specific guidelines for Command Query Responsibility Segregation audits.

install
source · Clone the upstream repo
git clone https://github.com/dykyi-roman/awesome-claude-code
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/dykyi-roman/awesome-claude-code "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/cqrs-knowledge" ~/.claude/skills/dykyi-roman-awesome-claude-code-cqrs-knowledge && rm -rf "$T"
manifest: skills/cqrs-knowledge/SKILL.md
source content

CQRS Knowledge Base

Quick reference for CQRS architecture patterns and PHP implementation guidelines.

Core Principles

Separation of Concerns

┌─────────────────────────────────────────────────────────────┐
│                      APPLICATION                            │
├─────────────────────────────────────────────────────────────┤
│   WRITE SIDE (Commands)     │     READ SIDE (Queries)       │
├─────────────────────────────┼───────────────────────────────┤
│ Command → Handler → Domain  │  Query → Handler → ReadModel  │
│ Changes state               │  Returns data, no side effects│
│ Uses Domain Model           │  Can bypass Domain Model      │
│ Single aggregate per cmd    │  Can join multiple sources    │
└─────────────────────────────┴───────────────────────────────┘

Rule: Commands WRITE, Queries READ. Never mix.

CQRS Components

ComponentPurposeReturnsSide Effects
CommandRequest to change statevoid or IDYes
CommandHandlerExecutes command logicvoid or IDYes
QueryRequest for dataData DTONo
QueryHandlerFetches and transforms dataData DTONo
CommandBusRoutes commands to handlersDependsN/A
QueryBusRoutes queries to handlersQuery resultN/A

Quick Checklists

Command Checklist

  • Named as imperative verb + noun (CreateOrder, ConfirmPayment)
  • Immutable (readonly class)
  • Contains only data needed for operation
  • Returns void or created ID (never entities)
  • One command = one aggregate affected
  • Validated before dispatch

Query Checklist

  • Named as Get/Find/List + noun (GetOrderDetails, ListCustomers)
  • Immutable (readonly class)
  • Contains filtering/pagination params
  • Handler has NO side effects
  • Can use optimized read models
  • Returns DTOs, not entities

Handler Checklist

  • Single
    execute()
    or
    __invoke()
    method
  • One handler per command/query
  • CommandHandler can dispatch domain events
  • QueryHandler never dispatches events
  • No cross-aggregate transactions in single handler

Common Violations Quick Reference

ViolationWhere to LookSeverity
Query with side effectsQueryHandler calling save()Critical
Command returning dataCommandHandler returning entityCritical
Mixed read/write in handlerHandler with both get and saveCritical
Business logic in handlerif/switch on domain stateWarning
Missing command validationCommand without invariantsWarning
Query using write DBQueryHandler using EntityManagerInfo

PHP 8.4 CQRS Patterns

Command

final readonly class CreateOrderCommand
{
    public function __construct(
        public CustomerId $customerId,
        /** @var array<OrderLineData> */
        public array $lines,
        public ?string $notes = null
    ) {
        if (empty($lines)) {
            throw new InvalidArgumentException('Order must have at least one line');
        }
    }
}

Command Handler

final readonly class CreateOrderHandler
{
    public function __construct(
        private OrderRepositoryInterface $orders,
        private EventDispatcherInterface $events
    ) {}

    public function __invoke(CreateOrderCommand $command): OrderId
    {
        $order = Order::create(
            id: OrderId::generate(),
            customerId: $command->customerId,
            lines: $command->lines
        );

        $this->orders->save($order);

        foreach ($order->releaseEvents() as $event) {
            $this->events->dispatch($event);
        }

        return $order->id();
    }
}

Query

final readonly class GetOrderDetailsQuery
{
    public function __construct(
        public OrderId $orderId
    ) {}
}

Query Handler

final readonly class GetOrderDetailsHandler
{
    public function __construct(
        private OrderReadModelInterface $readModel
    ) {}

    public function __invoke(GetOrderDetailsQuery $query): ?OrderDetailsDTO
    {
        return $this->readModel->findById($query->orderId);
    }
}

References

For detailed information, load these reference files:

  • references/command-patterns.md
    — Command structure, naming, validation
  • references/query-patterns.md
    — Query structure, read models
  • references/handler-patterns.md
    — Handler patterns, async/sync
  • references/bus-patterns.md
    — Command/Query bus implementations
  • references/antipatterns.md
    — Common violations with detection patterns