create-command
Generates CQRS Commands and Handlers for PHP 8.4. Creates immutable command DTOs with handlers that modify state. Includes unit tests.
Installation
Suivez les instructions du dépôt pour votre agent. Consultez les fichiers et dépendances avant l’installation.
Voir la source ↗GuidesInstructions
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
Exemples
Consultez les exemples du dépôt source.
Voir la source ↗Historique source
- Date d’indexation
- 2026-03-11
- Mise à jour de l’index
- 2026-03-11
- Branch
- main
Les dates concernent ce répertoire. Consultez le dépôt pour l’historique du code.
GitHub ↗chat Comments (0)
Sign in to join the discussion and leave a comment.
No comments yet. Be the first to share your thoughts!