jolicode / automapper

:rocket: Very FAST :rocket: PHP AutoMapper with on the fly code generation
https://automapper.jolicode.com/
MIT License
153 stars 15 forks source link

`skip_uninitialized_values` not working ? #189

Open TheoD02 opened 1 month ago

TheoD02 commented 1 month ago

I am trying to map a payload for a PATCH endpoint and would like to configure it so that:

However, the current behavior of skip_uninitialized_values is not working.

I have also tried using skip_null_values, but this is problematic because it skips both uninitialized and null values. In cases where a field is nullable (e.g., birthdate), this prevents setting a nullable field to null during a PATCH operation.

Example:

Here’s a basic example of my User entity:

class User
{
    private string $name;

    private ?\DateTimeInterface $birthdate = null; // Nullable
}

In a PATCH request, I would like the following behavior:

Here’s what the request payload might look like:

{
    "name": "John Doe",
    "birthdate": null
}

Expected Behavior:

Current Behavior:

Steps to Reproduce:

  1. Create a User entity with a nullable field (e.g., birthdate).
  2. Attempt to perform a PATCH request where some fields are not provided and others are explicitly set to null.
  3. Observe that uninitialized fields are not skipped correctly, or nullable fields can't be updated to null.

Questions:

MrMeshok commented 1 month ago
class User
{
    private string $name;

    private ?\DateTimeInterface $birthdate = null; // Nullable
}

When you type property with default value it already initialized on creation, so if you just remove = null it should work as expected.

TheoD02 commented 1 month ago
class User
{
    private string $name;

    private ?\DateTimeInterface $birthdate = null; // Nullable
}

When you type property with default value it already initialized on creation, so if you just remove = null it should work as expected.

Thanks for answer :)

Yes for that case, but in case you only want to update partially a resource, if birthdate is present, but name is not. An error will occur because mapper will attempt to map name but is uninitialized

MrMeshok commented 1 month ago

Can you provide full example with configuration for AutoMapper? I am testing with AutoMapper::create() without any configuration and have no errors

TheoD02 commented 1 month ago

Check here: https://phpsandbox.io/n/w5wwq#public/index.php

If I want to only update partially a resource, by setting only birthdate or lastName that will not work because other properties are uninitialized.

If birthdate is set to null or date, it should update value, otherwise it should not, for example

MrMeshok commented 1 month ago

I see now, for me, it's working because I was mapping from array/stdClass. When I was working with PATCH requests, I did this kind of mapping by hand. Yeah, it's kinda ugly with several if statements, but you can control all the logic

TheoD02 commented 1 month ago

I see now, for me, it's working because I was mapping from array/stdClass. When I was working with PATCH requests, I did this kind of mapping by hand. Yeah, it's kinda ugly with several if statements, but you can control all the logic

OK, thanks for your time, make it by hand need some effort that is not really needed in my case ^^

I think the preferable solution will be to split skip_uninitialized_values and skip_null_values to support both approach

joelwurtz commented 2 weeks ago

Indeed we don't support skip_uninitialized_values yet, would be a nice addition, will add this to roadmap

Korbeil commented 2 weeks ago

I started working on this mater and got something working, I need to fix some tests but the feature is there if you wanna take a look at it: https://github.com/jolicode/automapper/pull/200