rekalogika/mapper

Setter does not get called if the property is also in the constructor

Closed this issue · 1 comments

So the issue for me is - when you are trying to map onto an existing entity, which has constructor and setters - mapping does not work.

Here is an example:

class ParentObjDto
{
    public string $name;

    public ChildObjDto $child;
}
class ChildObjDto
{
    public string $a;
}
class ParentObj
{
    public function __construct(
        private string $name,
        private ChildObj $child,
    ) {
    }

    public function getChild(): ChildObj
    {
        return $this->child;
    }

    public function setChild(ChildObj $child): void
    {
        $this->child = $child;
    }

    public function getName(): string
    {
        return $this->name;
    }

    public function setName(string $name): void
    {
        $this->name = $name;
    }
}
class ChildObj
{
    public function __construct(
        private string $a,
    ) {
    }

    public function getA(): string
    {
        return $this->a;
    }

    public function setA(string $a): void
    {
        $this->a = $a;
    }
}

When you do mapping with a new object, passing target object class:

$dto = new ParentObjDto();
$dto->name = 'dto-name';
$dto->child = new ChildObjDto();
$dto->child->a = 'dto-a';

$entity = $this->map($dto, ParentObj::class);

... you get a perfect result:

 App\ParentObj {#1358
  -name: "dto-name"
  -child: 
  App\ChildObj {#1362
      -a: "dto-a"
  }
}

However, when you try to map onto existing object, let's say, doctrine entity fetched from DB:

$dto = new ParentObjDto();
$dto->name = 'dto-name';
$dto->child = new ChildObjDto();
$dto->child->a = 'dto-a';

$entity =  new ParentObj('entity-name', new ChildObj('entity-a'));
$entity = $this->map($dto, $entity);

... you properties are not changed

 App\ParentObj {#1258
  -name: "entity-name"
  -child: 
  App\ChildObj {#1362
      -a: "entity-a"
  }
}

Dunno, if it should be like that - but with the existence of setters, I would expect them to be used, cause you already have initialized object - no need for constructor. To make it work I need to remove properties from constructor.

The fix has been merged to #main. Thank you for your bug report.