Create cqrs commands
Prestashop Developer Skills
npx -y skills add jeffsenso/prestashop-skills --skill create-cqrs-commandsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Set up the full domain layer for a CQRS entity: identity value object, additional value objects, exception hierarchy, commands (Add, Edit, Delete, Toggle, sub-resource, or any custom domain action), and handler interfaces. Covers everything in src/Core/Domain/{Domain}/. Trigger: "create CQRS commands for {Domain}", "set up domain layer for {Domain}".
SKILL.md
5.6 KB, as published. Nobody here has run it
create-cqrs-commands
This skill creates the entire domain layer for an entity. It covers the Core side only
(interfaces and data objects) — handler implementations live in implement-cqrs-handlers.
Read CQRS/CONTEXT.md for conventions (scalar inputs/VO getters, exception hierarchy, handler rules).
1. Identity Value Object
Create src/Core/Domain/{Domain}/ValueObject/{Domain}Id.php:
- Constructor takes
int $value, validates$value > 0, throws{Domain}Exceptionif not - Single getter:
getValue(): int - No Symfony/Doctrine dependencies — pure PHP
Reference: src/Core/Domain/Tax/ValueObject/TaxId.php (simple), src/Core/Domain/Carrier/ValueObject/CarrierId.php (complex domain)
2. Additional Value Objects (if needed)
For fields with non-trivial validation or domain meaning (not just string/int):
- Enum-like fields: class with constants +
fromInt()/fromString()factory - URL fields: validate format in constructor
- Constrained numbers: range checks in constructor
Not every field needs a VO — only those with invariants beyond primitive type checking.
For has-many relations, create typed collections implementing \Countable and \IteratorAggregate.
3. Exception Hierarchy
Create in src/Core/Domain/{Domain}/Exception/ following the hierarchy documented in CQRS/CONTEXT.md: base, not-found, per-action, and constraint classes.
Reference: src/Core/Domain/Tax/Exception/ (simple), src/Core/Domain/Carrier/Exception/ (many constraint codes)
4. Commands
All commands live in src/Core/Domain/{Domain}/Command/.
4.1 Add command
Add{Domain}Command.php:
- Constructor takes all required fields as scalar typed parameters
- Optional fields use nullable types with defaults
- Multilingual fields:
array $localizedValueskeyed by language ID - Validate primitives in constructor (non-empty strings, positive ints)
- Getters can return VOs built from the scalar inputs
- Sub-resource fields are NOT included — they get their own command (see 4.5)
Reference: src/Core/Domain/Tax/Command/AddTaxCommand.php (simple), src/Core/Domain/Carrier/Command/AddCarrierCommand.php (many fields)
4.2 Edit command (partial-update pattern)
Edit{Domain}Command.php — follows the partial-update pattern from CQRS/CONTEXT.md:
- Constructor takes only the entity ID (as
int) - Every editable field:
private ?Type $field = null - Fluent setter:
public function setName(string $name): self { $this->name = $name; return $this; } - Nullable getter:
public function getName(): ?string { return $this->name; } - Do NOT include fields that are immutable after creation
Reference: src/Core/Domain/Tax/Command/EditTaxCommand.php (simple), src/Core/Domain/Manufacturer/Command/EditManufacturerCommand.php (with image)
4.3 Delete command
Delete{Domain}Command.php:
- Single constructor parameter:
int $id(scalar) - Getter returns VO:
getId(): {Domain}Id - No other properties — existence/constraint checks happen in the handler
4.4 Toggle status command
Toggle{Domain}StatusCommand.php (if entity has an active/enabled boolean):
- Constructor takes
int $idand optionallybool $expectedStatus - Handler reads current status and flips it, or sets to
$expectedStatusif provided - Used by the grid toggle switch (AJAX)
4.5 Sub-resource commands (if entity has has-many relations)
Set{Domain}{SubResource}sCommand.php — one command per sub-resource type:
- Constructor takes the entity
int $idand the full replacement collection (as array of scalars) - Getters return VOs as appropriate
- One command per sub-resource type
Reference: src/Core/Domain/Carrier/Command/SetCarrierRangesCommand.php
4.6 Custom domain actions
Any domain action that doesn't fit CRUD follows the same pattern: a command class with scalar constructor parameters and getters. The naming convention is {Verb}{Domain}Command.php.
5. Handler Interfaces
Create in src/Core/Domain/{Domain}/CommandHandler/:
- One interface per command:
Add{Domain}HandlerInterface,Edit{Domain}HandlerInterface, etc. - Single method:
public function handle({Action}{Domain}Command $command): void - Exception:
Add{Domain}HandlerInterface::handle()returns{Domain}Id(the new entity's ID) - All other handlers return
void
The concrete implementations live in src/Adapter/{Domain}/CommandHandler/ (see implement-cqrs-handlers skill).
6. Domain Interfaces (if needed)
For abstractions that cross the Core/Adapter boundary beyond the repository:
- File uploader:
{Domain}LogoFileUploaderInterfacein Core, implemented in Adapter - Use only Core domain types in signatures — no Doctrine/ObjectModel types
Rules
All conventions (scalar inputs/VO getters, exception hierarchy, handler rules) are in CQRS/CONTEXT.md. Skill-specific reminders:
- All validation failures throw domain exceptions from the constructor
- One handler interface per command — never combine multiple commands