Open dsoriano opened 3 weeks ago
Hey @dsoriano and thanks for using AutoMapper !
After some tests, you should use the transformer
on a class attribute as following:
#[MapTo(target: Target::class, property: 'address', transformer: 'getAddress', groups: ['write'])]
class Source
{
#[MapTo(target: Target::class, groups: ['write'])]
public string $name;
public string $street;
public string $zip;
public string $city;
public string $country;
public function getAddress(): TargetAddress
{
$targetAddress = new TargetAddress();
$targetAddress->street = $this->street;
$targetAddress->zip = $this->zip;
$targetAddress->city = $this->city;
$targetAddress->country = $this->country;
return $targetAddress;
}
}
To explain a bit: MapTo
attributes can only be placed onto properties or onto the class, so in your examples the MapTo
attribute on getAddress
was being ignored :wink:
You need to make it a class attribute that use the method as transformer so it works well :ok_hand:
This should fix your issue ! Tell me if you have anything else you wanna ask otherwise feel free to close the issue. Regards, Baptiste
Hi @Korbeil Thanks for your answer.
I'm pretty sure that the attribute MapTo on the method is not the problem and works. This code is working well :
class Source
{
#[MapTo(target: 'Target')]
public string $name;
public string $street;
public string $zip;
public string $city;
public string $country;
#[MapTo(target: 'Target', property: 'address')]
public function getAddress(): \stdClass
{
return (object)[
'street' => $this->street,
'zip' => $this->zip,
'city' => $this->city,
'country' => $this->country,
];
}
}
class TargetAddress {
public string $street;
public string $zip;
public string $city;
public string $country;
}
class Target
{
public string $name;
public ?TargetAddress $address = null;
}
$automapper = AutoMapper::create();
$source = new Source();
$source->name = 'John Doe';
$source->street = 'Main Street 123';
$source->zip = '12345';
$source->city = 'Springfield';
$source->country = 'USA';
$target = $automapper->map($source, new Target());
The dump :
The problem is coming when I add the serialization group. Event this code doesn't work :
#[MapTo(target: 'Target', property: 'address', groups: ['write'])]
public function getAddress(): TargetAddress
{
$address = new TargetAddress();
$address->street = $this->street;
$address->zip = $this->zip;
$address->city = $this->city;
$address->country = $this->country;
return $address;
}
Before your suggestion, the only workaround I found is to create another class SourceAddress like this:
class SourceAddress {
#[MapTo(target: 'TargetAddress', groups: ['write'])]
public string $street;
#[MapTo(target: 'TargetAddress', groups: ['write'])]
public string $zip;
#[MapTo(target: 'TargetAddress', groups: ['write'])]
public string $city;
#[MapTo(target: 'TargetAddress', groups: ['write'])]
public string $country;
}
And my method getAddress :
#[MapTo(target: 'Target', property: 'address', groups: ['write'])]
public function getAddress(): SourceAddress
{
$address = new SourceAddress();
$address->street = $this->street;
$address->zip = $this->zip;
$address->city = $this->city;
$address->country = $this->country;
return $address;
}
It seems confirm that this is a serialization group problem. But by using a new SourceAddress class and populate it manually for the mapping, I lost a little bit the benefits of an automapping.
Your code is working well also, but the problem is the transformer must return a TargetAddress class. This is restrictive if I want to use the same transformer for another target, and here again I lots the benefits of automapping if I have to populate a part of the target class manually.
Thank you
Hi all,
This is my use case :
I have to map the address fields from Source into an object in Target. There is a limitation : the target class can't be modified beause it comes from an external lib.
First I thought to do that :
But I doesn't work, It can convert the array to a new TargetAddress instance.
Then I tried :
Here the TargetAddress is created, but because of the group, the properties are not mapped.
Is there a way to do that simply ?
Thanks in advance