acc-create-query
SKILL.md
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/
{Name}Query.php— Immutable query DTO with parameters
Step 2: Generate Handler
Path: src/Application/{BoundedContext}/Handler/
{Name}Handler.php— Read model consumer
Step 3: Generate DTOs
Path: src/Application/{BoundedContext}/DTO/
{Name}DTO.php— Result data structurePaginatedResultDTO.php— For list queries (optional)
Step 4: Generate Read Model Interface
Path: src/Application/{BoundedContext}/ReadModel/
{Name}ReadModelInterface.php— Query methods contract
Step 5: Generate Tests
Path: tests/Unit/Application/{BoundedContext}/
File Placement
| Component | Path |
|---|---|
| Query | src/Application/{BoundedContext}/Query/ |
| Handler | src/Application/{BoundedContext}/Handler/ |
| DTO | src/Application/{BoundedContext}/DTO/ |
| Read Model Interface | src/Application/{BoundedContext}/ReadModel/ |
| Unit Tests | tests/Unit/Application/{BoundedContext}/ |
Query Naming Conventions
| Purpose | Query Name | Returns |
|---|---|---|
| Single by ID | GetOrderDetailsQuery |
DTO or throws |
| Single by field | FindUserByEmailQuery |
DTO or null |
| List/Collection | ListOrdersQuery |
PaginatedResult |
| Search | SearchProductsQuery |
array of DTOs |
| Count | CountPendingOrdersQuery |
int |
| Check existence | CheckEmailExistsQuery |
bool |
Quick Template Reference
Query
final readonly class {Name}Query
{
public function __construct(
public {IdType} $id
) {}
}
Query with Pagination
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
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-pattern | Problem | Solution |
|---|---|---|
| Side Effects | Handler modifies state | Keep read-only |
| Returning Entities | Leaking domain | Return DTOs only |
| No Validation | Invalid parameters | Validate in constructor |
| Unbounded Lists | Performance issues | Always paginate |
| Missing Read Model | Querying write model | Use dedicated read model |
References
For complete PHP templates and examples, see:
references/templates.md— Query, Handler, DTO, PaginatedResult, ReadModel templatesreferences/examples.md— GetOrderDetails, ListOrders, OrderDTO examples and tests
Weekly Installs
1
Repository
dykyi-roman/awe…ude-codeGitHub Stars
39
First Seen
Feb 11, 2026
Installed on
opencode1
claude-code1