Add DTO (Data Transfer Object) support to Queue plugin - #192
Open
skie wants to merge 8 commits into
Open
Conversation
Allows job payloads to be dispatched and received as typed DTO objects instead of plain arrays, while maintaining full backward compatibility with existing array-based jobs. - `QueueManager::push()` now accepts a DTO object directly, or a plain array paired with an explicit `dtoClass` option - New `Message::getDto()` / `getDtoClass()` to hydrate the payload back into the DTO on the receiving side — `getArgument()` still returns the raw array unchanged - Two hydration styles, matching CakePHP 5.4's own DTO conventions (`#[RequestToDto]`, `SelectQuery::projectAs()`): constructor reflection (with nested DTOs and `#[CollectionOf]`), and a static `createFromArray()` factory - `shouldBeUnique` dedupe hashing now factors in `dtoClass`, so two different DTO types with coincidentally identical data are never treated as duplicates of each other - Fully backward compatible — legacy array-only pushes produce byte-identical message bodies; `getDto()` gracefully returns `null` (never throws) when no DTO was dispatched or the recorded `dtoClass` can no longer be autoloaded
LordSimal
reviewed
Aug 8, 2026
LordSimal
reviewed
Aug 8, 2026
LordSimal
reviewed
Aug 8, 2026
LordSimal
reviewed
Aug 8, 2026
ADmad
reviewed
Aug 9, 2026
markstory
reviewed
Aug 10, 2026
|
|
||
| $dtoClass = $this->getDtoClass(); | ||
| if ($dtoClass === null) { | ||
| return null; |
Member
There was a problem hiding this comment.
This feels like an error condition to me.
Hydrate only the type the job asks for so a tampered queue body cannot choose which class is instantiated. Throw on failure instead of returning null.
markstory
approved these changes
Aug 13, 2026
Co-authored-by: Mark Story <mark@mark-story.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Allows job payloads to be dispatched and received as typed DTO objects instead of plain arrays, while maintaining full backward compatibility with existing array-based jobs.
Key Features:
QueueManager::push()now accepts a DTO object directly, or a plain array paired with an explicitdtoClassoption (metadata for uniqueness hashing / debugging)Message::getDto(ExpectedDto::class)hydrates the payload into the class the job asks for — the expected type comes from application code, not from the message body, so a tampered queue message cannot choose which class is instantiated.getArgument()still returns the raw array unchanged.getDtoClass()exposes anydtoClassrecorded at dispatch time as metadata only#[RequestToDto],SelectQuery::projectAs()): constructor reflection (with nested DTOs and#[CollectionOf]), and a staticcreateFromArray()factoryshouldBeUniquededupe hashing now factors indtoClass, so two different DTO types with coincidentally identical data are never treated as duplicates of each othergetDto()throws when the expected class is missing or the payload cannot be hydrated; jobs that still accept legacy arrays can catch that or keep usinggetArgument()Usage:
Note: requires bumping
cakephp/cakephpfrom^5.1.0to^5.4(needed forResultSetFactory::hydrateDto()/DtoMapper), plusphpfrom>=8.1to>=8.2to match. Since this raises the floor for every existing installation — not just DTO users — this should ship as3.0.0off a new3.xbranch rather than a2.xminor/patch release, with the version bump called out explicitly in the changelog/release notes.