Inheritance middle-layer doesn't get hydrated#6988
Conversation
| ; | ||
|
|
||
| $this->assertSame('Kevin', $persistedManager->name); | ||
| $this->assertSame('555-5555', $persistedManager->phoneNumber); |
72b7f8d to
ca85fe3
Compare
|
I added another test to show it working when using the |
ca85fe3 to
42f6bc6
Compare
42f6bc6 to
1a42971
Compare
| // the current discriminator value must be saved in order to disambiguate fields hydration, | ||
| // should there be field name collisions | ||
| if ($classMetadata->parentClasses && isset($this->_rsm->discriminatorColumns[$ownerMap])) { | ||
| $discriminatorValues = array_map( |
There was a problem hiding this comment.
@Ocramius @guilhermeblanco in theory this addition should have some impact on performance, but the overall result of phpbench in my machine is slightly better than it was before:
- ⅀T: 1,914,921.000μs μSD/r 0.000μs μRSD/r: 0.000%
+ ⅀T: 1,879,858.000μs μSD/r 0.000μs μRSD/r: 0.000%It's possible that my laptop is a bit crazy but... whatever.
Not sure if it's relevant for v2.x but for v3.x we could create the list of all discriminator values of the subclasses during the metadata creation.
Complete phpbench diff
\Doctrine\Performance\Hydration\SimpleQueryPartialObjectHydrationPerformanceBench
- benchHydration I0 P0 [μ Mo]/r: 109,739.000 109,739.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
+ benchHydration I0 P0 [μ Mo]/r: 95,171.000 95,171.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
\Doctrine\Performance\Hydration\SimpleQueryScalarHydrationPerformanceBench
- benchHydration I0 P0 [μ Mo]/r: 37,513.000 37,513.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
+ benchHydration I0 P0 [μ Mo]/r: 34,285.000 34,285.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
\Doctrine\Performance\Hydration\MixedQueryFetchJoinFullObjectHydrationPerformanceBench
- benchHydration I0 P0 [μ Mo]/r: 105,009.000 105,009.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
+ benchHydration I0 P0 [μ Mo]/r: 100,475.000 100,475.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
\Doctrine\Performance\Hydration\SimpleQueryFullObjectHydrationPerformanceBench
- benchHydration I0 P0 [μ Mo]/r: 337,610.000 337,610.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
+ benchHydration I0 P0 [μ Mo]/r: 329,276.000 329,276.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
\Doctrine\Performance\Hydration\SingleTableInheritanceInsertPerformanceBench
- benchInsertFixContracts I0 P0 [μ Mo]/r: 8,695.000 8,695.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
+ benchInsertFixContracts I0 P0 [μ Mo]/r: 7,281.000 7,281.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
- benchInsertFlexContracts I0 P0 [μ Mo]/r: 7,156.000 7,156.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
+ benchInsertFlexContracts I0 P0 [μ Mo]/r: 7,624.000 7,624.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
- benchInsertUltraContracts I0 P0 [μ Mo]/r: 8,162.000 8,162.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
+ benchInsertUltraContracts I0 P0 [μ Mo]/r: 7,510.000 7,510.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
- benchInsertAllContracts I0 P0 [μ Mo]/r: 11,867.000 11,867.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
+ benchInsertAllContracts I0 P0 [μ Mo]/r: 13,101.000 13,101.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
\Doctrine\Performance\Hydration\SingleTableInheritanceHydrationPerformanceBench
- benchHydrateFixContracts I0 P0 [μ Mo]/r: 3,520.000 3,520.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
+ benchHydrateFixContracts I0 P0 [μ Mo]/r: 3,815.000 3,815.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
- benchHydrateFlexContracts I0 P0 [μ Mo]/r: 4,791.000 4,791.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
+ benchHydrateFlexContracts I0 P0 [μ Mo]/r: 4,108.000 4,108.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
- benchHydrateUltraContracts I0 P0 [μ Mo]/r: 3,921.000 3,921.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
+ benchHydrateUltraContracts I0 P0 [μ Mo]/r: 3,636.000 3,636.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
- benchHydrateAllContracts I0 P0 [μ Mo]/r: 4,898.000 4,898.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
+ benchHydrateAllContracts I0 P0 [μ Mo]/r: 5,067.000 5,067.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
\Doctrine\Performance\Hydration\SimpleInsertPerformanceBench
- benchHydration I0 P0 [μ Mo]/r: 494,637.000 494,637.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
+ benchHydration I0 P0 [μ Mo]/r: 497,152.000 497,152.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
\Doctrine\Performance\Hydration\SimpleQueryArrayHydrationPerformanceBench
- benchHydration I0 P0 [μ Mo]/r: 53,799.000 53,799.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
+ benchHydration I0 P0 [μ Mo]/r: 50,772.000 50,772.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
\Doctrine\Performance\Hydration\MixedQueryFetchJoinPartialObjectHydrationPerformanceBench
- benchHydration I0 P0 [μ Mo]/r: 56,808.000 56,808.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
+ benchHydration I0 P0 [μ Mo]/r: 55,068.000 55,068.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
\Doctrine\Performance\Hydration\MixedQueryFetchJoinArrayHydrationPerformanceBench
- benchHydration I0 P0 [μ Mo]/r: 102,135.000 102,135.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
+ benchHydration I0 P0 [μ Mo]/r: 99,480.000 99,480.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
\Doctrine\Performance\Hydration\SimpleHydrationBench
- benchHydration I0 P0 [μ Mo]/r: 260,085.000 260,085.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
+ benchHydration I0 P0 [μ Mo]/r: 257,370.000 257,370.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
\Doctrine\Performance\ChangeSet\UnitOfWorkComputeChangesBench
- benchChangeSetComputation I0 P0 [μ Mo]/r: 1,536.000 1,536.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
+ benchChangeSetComputation I0 P0 [μ Mo]/r: 1,519.000 1,519.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
\Doctrine\Performance\LazyLoading\ProxyInitializationTimeBench
- benchCmsUserInitialization I0 P0 [μ Mo]/r: 69,404.000 69,404.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
+ benchCmsUserInitialization I0 P0 [μ Mo]/r: 65,095.000 65,095.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
- benchCmsEmployeeInitializationI0 P0 [μ Mo]/r: 11,635.000 11,635.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
+ benchCmsEmployeeInitializationI0 P0 [μ Mo]/r: 11,820.000 11,820.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
- benchInitializationOfAlreadyInitializedCmsUsersI0 P0 [μ Mo]/r: 777.000 777.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
+ benchInitializationOfAlreadyInitializedCmsUsersI0 P0 [μ Mo]/r: 822.000 822.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
- benchInitializationOfAlreadyInitializedCmsEmployeesI0 P0 [μ Mo]/r: 625.000 625.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
+ benchInitializationOfAlreadyInitializedCmsEmployeesI0 P0 [μ Mo]/r: 651.000 651.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
\Doctrine\Performance\LazyLoading\ProxyInstantiationTimeBench
- benchCmsUserInstantiation I0 P0 [μ Mo]/r: 127,576.000 127,576.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
+ benchCmsUserInstantiation I0 P0 [μ Mo]/r: 135,914.000 135,914.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
- benchCmsEmployeeInstantiation I0 P0 [μ Mo]/r: 93,023.000 93,023.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%
+ benchCmsEmployeeInstantiation I0 P0 [μ Mo]/r: 92,846.000 92,846.000 (μs) [μSD μRSD]/r: 0.000μs 0.00%There was a problem hiding this comment.
Not sure if it's relevant for
v2.xbut forv3.xwe could create the list of all discriminator values of the subclasses during the metadata creation.
More than that, questions to the metadata should be asked directly to the metadata, rather than done in random metadata consumers
There was a problem hiding this comment.
This block is an O(1) called at hydrator initialisation, if I'm not mistaken.
Please move it to a private method
There was a problem hiding this comment.
@lcobucci extremely flaky bench test results, but they seem to stay around normal values, so it is OK IMO
| if (isset($cacheKeyInfo['discriminatorColumn'], $data[$cacheKeyInfo['discriminatorColumn']]) | ||
| // Note: loose comparison required. See https://github.com/doctrine/doctrine2/pull/6304#issuecomment-323294442 | ||
| && ! in_array($data[$cacheKeyInfo['discriminatorColumn']], $cacheKeyInfo['discriminatorValues']) | ||
| && ! in_array((string) $data[$cacheKeyInfo['discriminatorColumn']], $cacheKeyInfo['discriminatorValues'], true) |
There was a problem hiding this comment.
In that comment @Ocramius says:
I checked the issue locally, and it's because the discriminator is not converted to a PHP value.
That said, trying to fix the issue leads to a massive can of worms that is being opened: let's keep the loose comparison there for now.
I've opened the can of worms and it wasn't that bad but it's possible that I've overlooked things, please use some ❤️ to review this commit
Ocramius
left a comment
There was a problem hiding this comment.
Besides code to be moved to a private method, looks OK 👍
| // the current discriminator value must be saved in order to disambiguate fields hydration, | ||
| // should there be field name collisions | ||
| if ($classMetadata->parentClasses && isset($this->_rsm->discriminatorColumns[$ownerMap])) { | ||
| $discriminatorValues = array_map( |
There was a problem hiding this comment.
Not sure if it's relevant for
v2.xbut forv3.xwe could create the list of all discriminator values of the subclasses during the metadata creation.
More than that, questions to the metadata should be asked directly to the metadata, rather than done in random metadata consumers
| // the current discriminator value must be saved in order to disambiguate fields hydration, | ||
| // should there be field name collisions | ||
| if ($classMetadata->parentClasses && isset($this->_rsm->discriminatorColumns[$ownerMap])) { | ||
| $discriminatorValues = array_map( |
There was a problem hiding this comment.
This block is an O(1) called at hydrator initialisation, if I'm not mistaken.
Please move it to a private method
| // the current discriminator value must be saved in order to disambiguate fields hydration, | ||
| // should there be field name collisions | ||
| if ($classMetadata->parentClasses && isset($this->_rsm->discriminatorColumns[$ownerMap])) { | ||
| $discriminatorValues = array_map( |
There was a problem hiding this comment.
@lcobucci extremely flaky bench test results, but they seem to stay around normal values, so it is OK IMO
|
@Ocramius please check if everything is good and |
77c5e98 to
1c45551
Compare
Hydrator was ignoring data from subclasses when using multiple inheritance levels. With this patch it will now use the discriminator values from all subclasses of the class being hydrated.
According to mapping drivers the discriminator values can always be converted to strings so it's safe to assume that we can actually do a strict comparison during hydration.
1c45551 to
f2da5bc
Compare
|
🐑 |
|
One unrelated test failed |
- `em` protected property - annotation namespace change - `QueryBuilder` instantiation
|
Forward-port in |
Inheritance middle-layer doesn't get hydrated
…es in `3.x` - `em` protected property - annotation namespace change - `QueryBuilder` instantiation
This is a failing test to show the issue.
Given the following inheritance structure:
Person <- Employee <- ManagerWhen hydrating a manager using a query builder created from the person repository, the employee's properties do not get hydrated.
I think this was caused by #6304.