Replies: 1 comment
|
Not deliberate. That fallback was a regression, and it is already fixed. The The current resolution is unconditional, // when metadata is read from the source, $mapping->source describes the
// reverse mapping and must not be resolved against $source
$sourcePropertyName = $readMetadataFromTarget ? $mapping->source ?? $propertyName : $propertyName;So the rule is about where the metadata was read from, not about readability. Metadata read from the target, which is your case since the Doctrine entity carries none, means I ran your exact snippet on php 8.4 against several releases: Worth noting that v8.1.0 was not right either, it was just right for your shape. Make Upgrade to 8.1.2 or newer and keep |
Uh oh!
There was an error while loading. Please reload this page.
What I'm trying to understand
I'm mapping an object that has no ObjectMapper metadata (a Doctrine entity) to a target DTO. A target property declares an explicit nested path, e.g.
#[Map(source: 'category.label')], while the source also exposes a property namedcategory(a related object, readable through a public getter).I noticed that whether the explicit
sourcepath is used depends on whether the same-named property is readable on the source, and I'd like to understand the intended semantics here.Where I see it
In
ObjectMapper::doMap()(branch8.1):So the explicit
$mapping->sourceis applied only when the target property name is not readable on the source; otherwise the same-named source property is read directly.I also noticed the effective behavior differs between two releases:
v8.1.0, the guard was!$refl->hasProperty($propertyName) || !isset($source->$propertyName). For aprivatesource property with a public getter,isset($source->$name)isfalse, so the explicitsourcepath was taken.v8.1.1(after [ObjectMapper] Fix mapping of private properties from parent classesΒ #63791),isReadable()goes through the PropertyAccessor and returnstruefor a property exposed via a public getter, so the same-named property is read directly instead of the explicitsourcepath.That difference is what prompted me to ask:
v8.1.1seems consistent (a property with a public getter genuinely is readable), so I assume the fallback semantics are deliberate β I just want to understand the design and the recommended usage.Small example
v8.1.0,$result->categoryis"hello"(thecategory.labelpath is followed).v8.1.1, the rawInnerfromgetCategory()is read instead of thecategory.labelpath.My questions
#[Map(source: '...')]acts as a fallback, applied only when the same-named property is not readable on the source? What's the reasoning behind keying it on readability of the target-property name?transform(e.g.#[Map(source: 'category', transform: ...)]), or giving the target property a different name (keeping the serialized key via#[SerializedName])?Thanks a lot for the guidance!
All reactions