AgentSkillsCN

acc-create-query

为 PHP 8.5 生成 CQRS 查询与处理器。创建仅用于读取的查询 DTO,并搭配无副作用的数据返回处理器,同时附带单元测试。

SKILL.md
--- frontmatter
name: acc-create-query
description: Generates CQRS Queries and Handlers for PHP 8.5. Creates read-only query DTOs with handlers that return data without side effects. Includes unit tests.

Query Generator

Generate CQRS-compliant Queries and Query Handlers with tests.

Query Characteristics

  • Immutable: final readonly class
  • Interrogative naming: Get/Find/List + noun
  • No side effects: Handler never modifies state
  • Returns DTOs: Never returns domain entities
  • Read-optimized: Can use dedicated read models

Generation Process

Step 1: Generate Query

Path: src/Application/{BoundedContext}/Query/

  1. {Name}Query.php — Immutable query DTO with parameters

Step 2: Generate Handler

Path: src/Application/{BoundedContext}/Handler/

  1. {Name}Handler.php — Read model consumer

Step 3: Generate DTOs

Path: src/Application/{BoundedContext}/DTO/

  1. {Name}DTO.php — Result data structure
  2. PaginatedResultDTO.php — For list queries (optional)

Step 4: Generate Read Model Interface

Path: src/Application/{BoundedContext}/ReadModel/

  1. {Name}ReadModelInterface.php — Query methods contract

Step 5: Generate Tests

Path: tests/Unit/Application/{BoundedContext}/


File Placement

ComponentPath
Querysrc/Application/{BoundedContext}/Query/
Handlersrc/Application/{BoundedContext}/Handler/
DTOsrc/Application/{BoundedContext}/DTO/
Read Model Interfacesrc/Application/{BoundedContext}/ReadModel/
Unit Teststests/Unit/Application/{BoundedContext}/

Query Naming Conventions

PurposeQuery NameReturns
Single by IDGetOrderDetailsQueryDTO or throws
Single by fieldFindUserByEmailQueryDTO or null
List/CollectionListOrdersQueryPaginatedResult
SearchSearchProductsQueryarray of DTOs
CountCountPendingOrdersQueryint
Check existenceCheckEmailExistsQuerybool

Quick Template Reference

Query

php
final readonly class {Name}Query
{
    public function __construct(
        public {IdType} $id
    ) {}
}

Query with Pagination

php
final readonly class List{Name}Query
{
    public function __construct(
        public ?{FilterType} $filter = null,
        public int $limit = 20,
        public int $offset = 0,
        public string $sortBy = 'created_at',
        public string $sortDirection = 'desc'
    ) {
        if ($limit < 1 || $limit > 100) {
            throw new \InvalidArgumentException('Limit must be between 1 and 100');
        }
    }
}

Handler

php
final readonly class {Name}Handler
{
    public function __construct(
        private {ReadModelInterface} $readModel
    ) {}

    public function __invoke({Name}Query $query): {ResultDTO}
    {
        $result = $this->readModel->findById($query->id->value);

        if ($result === null) {
            throw new {NotFoundException}($query->id);
        }

        return $result;
    }
}

Anti-patterns to Avoid

Anti-patternProblemSolution
Side EffectsHandler modifies stateKeep read-only
Returning EntitiesLeaking domainReturn DTOs only
No ValidationInvalid parametersValidate in constructor
Unbounded ListsPerformance issuesAlways paginate
Missing Read ModelQuerying write modelUse dedicated read model

References

For complete PHP templates and examples, see:

  • references/templates.md — Query, Handler, DTO, PaginatedResult, ReadModel templates
  • references/examples.md — GetOrderDetails, ListOrders, OrderDTO examples and tests