mark-gerarts / automapper-plus

An AutoMapper for PHP
MIT License
551 stars 30 forks source link

What about polymorphism? #67

Closed praad closed 2 years ago

praad commented 3 years ago

Is there any easy way to map polymorph property?

The polymorph property can be class A or B or C. Both classes extends the same abstract classes. Unfortunately I can not make a mapper for the abstract class itself.

mark-gerarts commented 3 years ago

Polymorphism is supported. If no mapping is found, we will look up the inheritance chain to see if a parent mapping is registered. Take a look at the following snipper:

abstract class BaseClass
{
    public $sharedProperty = 'shared';
}

class A extends BaseClass
{
}

$config = new AutoMapperConfig();
$mapper = new AutoMapper($config);

$config->registerMapping(BaseClass::class, \stdClass::class)
    ->forMember('sharedProperty', Operation::setTo('Set in base mapping'));

// This works because A extends the BaseClass, which is registered.
$result = $mapper->map(new A(), \stdClass::class);
var_dump($result->sharedProperty); // "Set in base mapping"

// If you register a more specific mapping for A, that one is used instead
$config->registerMapping(A::class, \stdClass::class);
$result = $mapper->map(new A(), \stdClass::class);
var_dump($result->sharedProperty); // "shared"

// ...but you can copy from the base mapping to prevent duplicate code.
$config->registerMapping(A::class, \stdClass::class)
    ->copyFrom(BaseClass::class, \stdClass::class);
$result = $mapper->map(new A(), \stdClass::class);
var_dump($result->sharedProperty); // "Set in base mapping"

I've used \stdClass here, because I noticed a bug with polymorphism when mapping to/from array - perhaps this is what you are doing? I'll look into fixing it.

mark-gerarts commented 3 years ago

Mapping from an array has been fixed (mapping to an array is not available in 1.x).

Let me know if the above provides an answer for you!

peter-si commented 3 years ago

@praad I believe you want to map that polymorphic property to something like this? A -> ADto B -> BDto C -> CDto

If so check out my recent pull request https://github.com/mark-gerarts/automapper-plus/pull/70 where I added mapToMultiple operation

praad commented 3 years ago

Hi Peter! Yes I need a solution like this. How can I include your new feature by composer.json to our existing project to test?

peter-si commented 3 years ago

@praad try adding my repo as private repository and add it to composer json as

    "require": {
        "peter-si/automapper-plus": "dev-map_to_any_of"
    },
mark-gerarts commented 3 years ago

I'll look into the PR this weekend, and if all is well I'll tag a new release.

fd6130 commented 2 years ago

Can close this issue since #70 already merged.