create-command
Generates CQRS Commands and Handlers for PHP 8.4. Creates immutable command DTOs with handlers that modify state. Includes unit tests.
安装与使用
请根据来源仓库和你的 AI 工具说明安装此技能。先阅读技能文件和依赖要求,再添加到工作流。
查看来源 ↗使用指南技能说明
Command Generator
Generate CQRS-compliant Commands and Command Handlers with tests.
Command Characteristics
-
Immutable:
final readonly class - Imperative naming: Verb + noun (CreateOrder, ConfirmPayment)
- Self-validating: Validates invariants in constructor
- Intent-revealing: Name describes what should happen
- Returns void or ID: Never returns data
Generation Process
Step 1: Generate Command
Path: src/Application/{BoundedContext}/Command/
-
{Name}Command.php— Immutable command DTO
Step 2: Generate Handler
Path: src/Application/{BoundedContext}/Handler/
-
{Name}Handler.php— Command processor
Step 3: Generate Tests
Path: tests/Unit/Application/{BoundedContext}/
File Placement
| Component | Path |
|---|---|
| Command | src/Application/{BoundedContext}/Command/ |
| Handler | src/Application/{BoundedContext}/Handler/ |
| Unit Tests | tests/Unit/Application/{BoundedContext}/ |
Command Naming Conventions
| Action | Command Name | Returns |
|---|---|---|
| Create new | CreateOrderCommand |
ID |
| Confirm/Approve | ConfirmOrderCommand |
void |
| Cancel/Reject | CancelOrderCommand |
void |
| Update property | UpdateShippingAddressCommand |
void |
| Add child | AddOrderLineCommand |
void |
| Remove child | RemoveOrderLineCommand |
void |
Quick Template Reference
Command
final readonly class {Name}Command
{
public function __construct(
public {ValueObject} $id,
public string $data
) {
if (empty($data)) {
throw new \InvalidArgumentException('Data is required');
}
}
public static function fromArray(array $data): self
{
return new self(
id: new {ValueObject}($data['id']),
data: $data['data']
);
}
}
Handler (Update Flow)
final readonly class {Name}Handler
{
public function __construct(
private {Repository}Interface $repository,
private EventDispatcherInterface $events
) {}
public function __invoke({Name}Command $command): void
{
$aggregate = $this->repository->findById($command->id);
if ($aggregate === null) {
throw new NotFoundException($command->id);
}
$aggregate->doSomething($command->data);
$this->repository->save($aggregate);
foreach ($aggregate->releaseEvents() as $event) {
$this->events->dispatch($event);
}
}
}
Handler (Create Flow)
public function __invoke(CreateCommand $command): AggregateId
{
$aggregate = Aggregate::create(
id: $this->repository->nextIdentity(),
...
);
$this->repository->save($aggregate);
foreach ($aggregate->releaseEvents() as $event) {
$this->events->dispatch($event);
}
return $aggregate->id();
}
Anti-patterns to Avoid
| Anti-pattern | Problem | Solution |
|---|---|---|
| Returning Data | Query through command | Use Query for reads |
| No Validation | Invalid commands | Validate in constructor |
| Business Logic | Handler has decisions | Delegate to aggregate |
| Missing Events | Events not dispatched | Always dispatch after save |
| Direct Persistence | Bypassing aggregate | Always use aggregate methods |
References
For complete PHP templates and examples, see:
-
references/templates.md— Command, Handler, Test templates with patterns -
references/examples.md— CreateOrder, ConfirmOrder, CancelOrder examples and tests
使用示例
查看来源仓库中的使用示例与配置说明。
查看来源 ↗来源历史
- 收录时间
- 2026-03-11
- 索引更新时间
- 2026-03-11
- Branch
- main
收录与同步日期属于本站记录。源码修改历史请查看来源仓库。
GitHub ↗chat Comments (0)
Sign in to join the discussion and leave a comment.
No comments yet. Be the first to share your thoughts!