doctrine / doctrine-laminas-hydrator

Doctrine hydrators for Laminas applications
https://www.doctrine-project.org/projects/doctrine-laminas-hydrator.html
MIT License
33 stars 19 forks source link

Association extraction #79

Open misterx opened 1 year ago

misterx commented 1 year ago

I want to use this library without laminas forms. When I try to extract an entity with a many-to-many relationship, I receive the PersistentCollection in the result array. Association extraction is not covered in the documentation. Could you please help me?

Here is my example entities:

#[ORM\Entity]
class Order extends IdEntity
{
    #[ORM\Id]
    #[ORM\Column(type: 'string')]
    protected string $id;

    #[ORM\ManyToMany(targetEntity: Tag::class)]
    public Collection $tags;

    public function __construct()
    {
        $this->id = uniqid('order');
        $this->tags = new ArrayCollection();
    }

    public function getId():string
    {
        return $this->id;
    }

    public function getTags():Collection
    {
        return $this->tags;
    }
}

#[ORM\Entity]
final class Tag extends IdEntity
{
    #[ORM\Id]
    #[ORM\Column(type: 'string')]
    public string $id;

    #[ORM\Column(type: 'string')]
    public string $name;

    public function __construct()
    {
        $this->id = uniqid('tag');
    }

    public function getId():string
    {
        return $this->id;
    }

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

Here is my code where i'm trying to extract data:

$order = $entityManager->find(Order::class,'order641c4493aa1ad');
$doctrineHydrator = new \Doctrine\Laminas\Hydrator\DoctrineObject($entityManager);
$data = $doctrineHydrator->extract($order);
print_r(get_debug_type($data['tags']));

Here is output:

Doctrine\ORM\PersistentCollection

I'm expecting array with tags there.

driehle commented 9 months ago

I can confirm that the same is happening in our unit tests as well.

In testExtractOneToOneAssociationByReference the output is:

array(2) {
  ["id"]=>
  int(2)
  ["toOne"]=>
  object(DoctrineTest\Laminas\Hydrator\Assets\ByValueDifferentiatorEntity)#25951 (2) {
    ["id":protected]=>
    int(2)
    ["field":protected]=>
    string(3) "foo"
  }
}

However, that should more likely be:

array(2) {
  ["id"]=>
  int(2)
  ["toOne"]=>
  array (2) {
    ["id"]=>
    int(2)
    ["field"]=>
    string(3) "foo"
  }
}

In testExtractOneToManyAssociationByValue the output is:

array(2) {
  ["id"]=>
  int(4)
  ["entities"]=>
  object(Doctrine\Common\Collections\ArrayCollection)#47880 (1) {
    ["elements":"Doctrine\Common\Collections\ArrayCollection":private]=>
    array(2) {
      [0]=>
      object(DoctrineTest\Laminas\Hydrator\Assets\ByValueDifferentiatorEntity)#46779 (2) {
        ["id":protected]=>
        int(2)
        ["field":protected]=>
        string(32) "Modified from getEntities getter"
      }
      [1]=>
      object(DoctrineTest\Laminas\Hydrator\Assets\ByValueDifferentiatorEntity)#41983 (2) {
        ["id":protected]=>
        int(3)
        ["field":protected]=>
        string(32) "Modified from getEntities getter"
      }
    }
  }
}

However, that should more likely be:

array(2) {
  ["id"]=>
  int(4)
  ["entities"]=>
  array(2) {
    [0]=>
    array (2) {
      ["id"]=>
      int(2)
      ["field"]=>
      string(32) "Modified from getEntities getter"
    }
    [1]=>
    array (2) {
      ["id"]=>
      int(3)
      ["field"]=>
      string(32) "Modified from getEntities getter"
    }
  }
}

I guess that no one has ever recognized this yet as it doesn't make a difference to laminas-form, since the Doctrine objects are array-accessible and, hence, work the same way as arrays when populating form data to Laminas forms.