diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index bd9ebea8d28..ef8053a211c 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -40,5 +40,10 @@ jobs: with: dependency-versions: "highest" + - name: "Add orphan metadata where needed" + run: | + printf '%s\n\n%s\n' ":orphan:" "$(cat docs/en/sidebar.rst)" > docs/en/sidebar.rst + printf '%s\n\n%s\n' ":orphan:" "$(cat docs/en/reference/installation.rst)" > docs/en/reference/installation.rst + - name: "Run guides-cli" run: "vendor/bin/guides -vvv --no-progress docs/en 2>&1 | grep -v 'No template found for rendering directive' | ( ! grep WARNING )" diff --git a/docs/en/reference/installation.rst b/docs/en/reference/installation.rst index 2c0d5823009..dab1364f777 100644 --- a/docs/en/reference/installation.rst +++ b/docs/en/reference/installation.rst @@ -1,5 +1,3 @@ -:orphan: - Installation ============ diff --git a/docs/en/sidebar.rst b/docs/en/sidebar.rst index 619c6e2511a..db7da890ac9 100644 --- a/docs/en/sidebar.rst +++ b/docs/en/sidebar.rst @@ -1,5 +1,3 @@ -:orphan: - .. toc:: .. tocheader:: Tutorials diff --git a/src/UnitOfWork.php b/src/UnitOfWork.php index e1336140640..4577ccb6648 100644 --- a/src/UnitOfWork.php +++ b/src/UnitOfWork.php @@ -2662,7 +2662,19 @@ private function eagerLoadCollections(array $collections, ToManyInverseSideMappi foreach ($found as $targetValue) { $sourceEntity = $targetProperty->getValue($targetValue); - $id = $this->identifierFlattener->flattenIdentifier($class, $class->getIdentifierValues($sourceEntity)); + if ($sourceEntity === null && isset($targetClass->associationMappings[$mappedBy]['joinColumns'])) { + // case where the hydration $targetValue itself has not yet fully completed, for example + // in case a bi-directional association is being hydrated and deferring eager loading is + // not possible due to subclassing. + $data = $this->getOriginalEntityData($targetValue); + $id = []; + foreach ($targetClass->associationMappings[$mappedBy]['joinColumns'] as $joinColumn) { + $id[] = $data[$joinColumn['name']]; + } + } else { + $id = $this->identifierFlattener->flattenIdentifier($class, $class->getIdentifierValues($sourceEntity)); + } + $idHash = implode(' ', $id); if ($mapping->indexBy !== null) { diff --git a/tests/Tests/Models/AbstractFetchEager/AbstractRemoteControl.php b/tests/Tests/Models/AbstractFetchEager/AbstractRemoteControl.php new file mode 100644 index 00000000000..6ef67359e99 --- /dev/null +++ b/tests/Tests/Models/AbstractFetchEager/AbstractRemoteControl.php @@ -0,0 +1,35 @@ + 'MobileRemoteControl'])] +abstract class AbstractRemoteControl +{ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: 'integer')] + public int $id; + + #[ORM\Column(type: 'string')] + public string $name; + + /** @var Collection */ + #[ORM\OneToMany(targetEntity: User::class, mappedBy: 'remoteControl', fetch: 'EAGER')] + public Collection $users; + + public function __construct(string $name) + { + $this->name = $name; + $this->users = new ArrayCollection(); + } +} diff --git a/tests/Tests/Models/AbstractFetchEager/MobileRemoteControl.php b/tests/Tests/Models/AbstractFetchEager/MobileRemoteControl.php new file mode 100644 index 00000000000..c9246036741 --- /dev/null +++ b/tests/Tests/Models/AbstractFetchEager/MobileRemoteControl.php @@ -0,0 +1,12 @@ +remoteControl = $control; + } +} diff --git a/tests/Tests/ORM/Functional/AbstractFetchEagerTest.php b/tests/Tests/ORM/Functional/AbstractFetchEagerTest.php new file mode 100644 index 00000000000..c8166c3d03d --- /dev/null +++ b/tests/Tests/ORM/Functional/AbstractFetchEagerTest.php @@ -0,0 +1,37 @@ +createSchemaForModels( + AbstractRemoteControl::class, + User::class, + ); + + $control = new MobileRemoteControl('smart'); + $user = new User($control); + + $entityManage = $this->getEntityManager(); + + $entityManage->persist($control); + $entityManage->persist($user); + $entityManage->flush(); + $entityManage->clear(); + + $user = $entityManage->find(User::class, $user->id); + + self::assertNotNull($user); + self::assertEquals('smart', $user->remoteControl->name); + self::assertTrue($user->remoteControl->users->contains($user)); + } +}