Install
$ agentstack add skill-jeffsenso-prestashop-skills-implement-cqrs-handlers ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
implement-cqrs-handlers
Handlers live in src/Adapter/{Domain}/CommandHandler/ and QueryHandler/. See [CQRS/CONTEXT.md](../../CONTEXT.md#handlers) for conventions (#[AsCommandHandler]/#[AsQueryHandler] attributes, no cross-handler calls, return types).
1. Add handler
Add{Domain}Handler.php implementing Add{Domain}HandlerInterface:
- Inject
{Domain}Repository handle(Add{Domain}Command $command): {Domain}Id:- Construct the ObjectModel entity from command data
- For multilingual fields, map
$command->getLocalizedNames()to the lang array - Call
$this->repository->create(...) - Return the new
{Domain}Id - Catch persistence exceptions, rethrow as domain exceptions
Reference: src/Adapter/Tax/CommandHandler/AddTaxHandler.php (simple), src/Adapter/Manufacturer/CommandHandler/AddManufacturerHandler.php (with image)
2. Edit handler (partial-update)
Edit{Domain}Handler.php implementing Edit{Domain}HandlerInterface:
- Load entity:
$entity = $this->repository->get{Domain}($command->getId()) - For each field:
if ($command->getName() !== null) { $entity->name = $command->getName(); } - Apply only non-null fields — never overwrite with null
- Call
$this->repository->update($entity) - Sub-resource commands are dispatched independently, not composed here
Reference: src/Adapter/Tax/CommandHandler/EditTaxHandler.php (simple), src/Adapter/Carrier/CommandHandler/EditCarrierHandler.php (many fields)
3. Delete handler
Delete{Domain}Handler.php implementing Delete{Domain}HandlerInterface:
- Load entity to verify existence (throws
{Domain}NotFoundException) - Check business constraints: if entity is referenced by active orders/other entities, throw
CannotDelete{Domain}Exception - Call
$this->repository->delete($command->getId())
4. Toggle status handler
Toggle{Domain}StatusHandler.php:
- Load entity by ID
- Flip:
$entity->active = !$entity->active - Call repository update
- Return void — the controller reads back state from the grid
5. Sub-resource handler (if sub-resources exist)
Set{Domain}{SubResource}sHandler.php:
Two strategies depending on complexity:
Strategy A: Atomic replace (simpler, quicker)
Used when sub-resources have no identity of their own or when maintaining existing rows isn't important:
- Begin a DB transaction
- Delete all existing sub-resource rows for the entity
- Insert new rows from
$command->getItems() - Commit; on failure, rollback and throw domain exception
- Empty array = delete all (valid use case)
Reference: src/Adapter/Carrier/CommandHandler/SetCarrierRangesHandler.php
Strategy B: Incremental update (cleaner, preserves existing sub-resources)
Preferred when sub-resources have their own identity or when preserving existing rows matters (e.g., to keep audit trails, auto-increment IDs, or related data):
- Load existing sub-resources for the entity
- Compare with the new collection: identify additions, updates, and removals
- Apply only the necessary changes (insert new, update changed, delete removed)
- Wrap in a transaction
Choose Strategy B when possible for cleaner data management. Use Strategy A when sub-resources are simple value-like collections without individual identity.
6. Get-for-editing handler
Get{Domain}ForEditingHandler.php in QueryHandler/:
- Load entity via repository
- Map ALL fields to the return DTO: scalars, multilingual (array keyed by langId), related IDs
- Return typed
Editable{Domain}DTO (with scalar types only — no VOs in the DTO) - No write side effects
Reference: src/Adapter/Tax/QueryHandler/GetTaxForEditingHandler.php (simple)
7. List query handler (if explicit query exists)
Most domains use the grid QueryBuilder pattern — no handler needed. Only create if the domain uses an explicit Get{Domain}sForListing query class.
Rules
Conventions (attributes, no SQL, no cross-handler calls, return types) are in [CQRS/CONTEXT.md](../../CONTEXT.md#handlers). Skill-specific reminders:
- Check null before every field update in Edit handler (partial-update pattern)
- Always verify existence before deletion — never delete blindly
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: jeffsenso
- Source: jeffsenso/prestashop-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.