Orm: Hydration not working for Embeddables with php 7.4 typed properties

Created on 7 Oct 2019  路  10Comments  路  Source: doctrine/orm

Bug Report

| Q | A
|------------ | ------
| BC Break | no
| Version | 2.6.4

Summary

There is an error when using php 7.4 and trying to fetch an entity from the database that has typed properties containing value objects that are mapped as embeddables.

Current behavior

There is a fatal error.

Fatal error: Uncaught Error: Typed property App\Domain\Entity\City\City::$id must not be accessed before initialization in /var/www/vendor/doctrine/or
m/lib/Doctrine/ORM/Mapping/ReflectionEmbeddedProperty.php:89
Stack trace:
#0 /var/www/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ReflectionEmbeddedProperty.php(89): ReflectionProperty->getValue(Object(App\Domain\Entity\Cit
y\City))
#1 /var/www/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php(2670): Doctrine\ORM\Mapping\ReflectionEmbeddedProperty->setValue(Object(App\Domain\Ent
ity\City\City), '29df4356-b832-4...')
#2 /var/www/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php(271): Doctrine\ORM\UnitOfWork->createEntity('App\\Domain\\Enti.
..', Array, Array)
#3 /var/www/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php(492): Doctrine\ORM\Internal\Hydration\ObjectHydrator->getEntity
(Array, 'c')
#4 /var/www/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php(162): Doctrine\ORM\Internal\Hydration\ObjectHyd in /var/www/ven
dor/doctrine/orm/lib/Doctrine/ORM/Mapping/ReflectionEmbeddedProperty.php on line 89

How to reproduce

$this
            ->entityManager
            ->createQueryBuilder()
            ->select('c')
            ->from(City::class, 'c')
            ->where('c.id.id = :id')
            ->setParameter('id', $id)
            ->getQuery()
            ->getOneOrNullResult();
<?php
namespace App\Domain\Entity\City;
use App\Domain\Entity\City\ValueObject\CityId;

class City
{
    private CityId $id;
}
<?php
namespace App\Domain\Entity\City\ValueObject;

final class CityId
{
    private string $id;

    private function __construct(string $id)
    {
        $this->id = $id;
    }
}



md5-c16e00f7d8e79945fc87e0b36f4fbcf9



```xml
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
                          https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">

    <embeddable name="App\Domain\Entity\City\ValueObject\CityId">
        <id name="id" type="guid" column="id">
            <generator strategy="NONE" />
        </id>
    </embeddable>
</doctrine-mapping>

Expected behavior

The entity should be fetched from the database and hydrated.

Most helpful comment

Any updates on this issue?

All 10 comments

@sspat can you isolate this into a test case? I think we'll need to add overhead to ReflectionEmbeddedProperty so that it checks whether the property was initialized (new PHP 7.4 API)

@Ocramius Added the testcase, can I be of any further assistance on this issue?

@sspat Do you like to add a fix for the failing test?

@SenseException Could you explain please, what did you mean? The test failing on <=7.3, or the fix for the bug itself? Thanks

@lcobucci @SenseException moved the test entity to a separate file, all tests passing now on <=7.3

The fix of the bug itself. :-) Thank you for your work.

Any updates on this issue?

Updates can be found in the corresponding PR #7857.

The solution "appears" to be simple. In ReflectionEmbeddedProperty.php change line 89:

$embeddedObject = $this->parentProperty->getValue($object);

to

$embeddedObject = $this->parentProperty->isInitialized($object) ? $this->parentProperty->getValue($object) : null;

I've tried to read as much of the open issues/PR/history on this matter and it appears that the solution will be to create a ReflectionEmbeddedProperty74 class which is used instead for PHP 7,4? Tests appear to be written in the PR mentioned above.

Am I missing anything? I'm happy to contribute or wait, whichever is required. Performance implications were implied however, I'm unable to find these.

Per https://github.com/doctrine/orm/pull/7857#issuecomment-575537801, I believe this is fixed in doctrine/persistence.

Was this page helpful?
0 / 5 - 0 ratings