Skip to content

[ObjectMapper] handle non existing property errors #60856

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: 7.3
Choose a base branch
from

Conversation

soyuka
Copy link
Contributor

@soyuka soyuka commented Jun 20, 2025

Q A
Branch? 7.3
Bug fix? yes
New feature? no
Deprecations? no
Issues Fix #60848
License MIT

The property accessor allows to ignore exceptions when a property does not exist. Without the property accessor we now throw a proper exception when the property does not exist (as opposed to the PHP Warning it'd trigger otherwise). I think its better to thrown then to hide the error in that particular case.

This fixes #60848 providing a working solution and a better DX, especially that in PHP the behavior of dynamic properties is to avoid them as much as possible.

@soyuka soyuka force-pushed the default-value-stdclass branch from c6a7f6d to 88a4a59 Compare June 20, 2025 14:12
@tacman
Copy link
Contributor

tacman commented Jun 20, 2025

Hmm. I'm not sure why this is a non-existing property error.

The DTO has the property $extra, with a default of null (or something else).

The source object is a simple StdClass that doesn't have the property. It's not setting a non-existing property of the target object, but rather set a default on the target object when the source object is missing the field.

I think it's a pretty common case -- the source and target have some common fields, create the target object and map with the property name is the same or the property has a #[Map()] attribute.

@tacman
Copy link
Contributor

tacman commented Jun 20, 2025

the "isset" was just something I tried because it seemed like logic that would work, but didn't. Could be a different issue.

@nicolas-grekas nicolas-grekas modified the milestones: 7.4, 7.3 Jun 20, 2025
@symfony symfony deleted a comment from carsonbot Jun 20, 2025
@soyuka
Copy link
Contributor Author

soyuka commented Jun 21, 2025

The source object is a simple StdClass that doesn't have the property. It's not setting a non-existing property of the target object, but rather set a default on the target object when the source object is missing the field.

In your example:

$mapper = new ObjectMapper();
$target = 'App\Dto\MyClass';
$obj = (object) ['id'=>'abc'];
$entity = $mapper->map($obj, $target);

The stdClass does not have any information about how it should be mapped, therefore we use the data from the $target (here App\Dto\MyClass. App\Dto\MyClass has a default but when we read that property on the stdClass it does not exists. So it's not "setting a non-existing property" but "reading a non-existing property" which leads to a NoSuchPropertyException. Looks fine to me.
The default value works fine when using the PropertyAccessor with the proper option see my assertions in the tests:

        $this->assertEquals('abc', $b->id);
        $this->assertEquals(null, $b->optional);

I think it's a pretty common case -- the source and target have some common fields, create the target object and map with the property name is the same or the property has a #[Map()] attribute.

stdClass is quite specific, use DTOs on both ends of the mapping and you probably won't have any issues.

the "isset" was just something I tried because it seemed like logic that would work, but didn't. Could be a different issue.

Isset would be a weird use case but NotNull would be quite useful.

@tacman
Copy link
Contributor

tacman commented Jun 21, 2025

Thanks. My use case is that I'm getting data from csv and JSON, and I want to map the data to a DTO. But the field names and often type are wrong.

So

First Name,Last Name,Country,Language Spoken At Home
Bob,Roberts,USA,English

And I want a DTO of a class with properties $firstName, $lastName,$countryCode,$langCode

So I want to import from $row['First Name'] to $dto->firstName and transform the country and language names to codes them with a service. ObjectMapper seems like the perfect tool for that. So this step is to go from the stdClass to a DTO. What approach do you suggest? I've been using league/csv-reader for some parts, (which will map to a DTO), but the problem is that I don't have a DTO yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[ObjectMapper] if 'isset' and default values not working
4 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy