Skip to content

Commit 196d3a6

Browse files
committed
Merge remote-tracking branch 'origin/2.19.x' into 3.1.x
2 parents 716fc97 + abcad6f commit 196d3a6

File tree

8 files changed

+128
-5
lines changed

8 files changed

+128
-5
lines changed

.github/workflows/documentation.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,10 @@ jobs:
4040
with:
4141
dependency-versions: "highest"
4242

43+
- name: "Add orphan metadata where needed"
44+
run: |
45+
printf '%s\n\n%s\n' ":orphan:" "$(cat docs/en/sidebar.rst)" > docs/en/sidebar.rst
46+
printf '%s\n\n%s\n' ":orphan:" "$(cat docs/en/reference/installation.rst)" > docs/en/reference/installation.rst
47+
4348
- name: "Run guides-cli"
4449
run: "vendor/bin/guides -vvv --no-progress docs/en 2>&1 | grep -v 'No template found for rendering directive' | ( ! grep WARNING )"

docs/en/reference/installation.rst

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
:orphan:
2-
31
Installation
42
============
53

docs/en/sidebar.rst

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
:orphan:
2-
31
.. toc::
42

53
.. tocheader:: Tutorials

src/UnitOfWork.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2662,7 +2662,19 @@ private function eagerLoadCollections(array $collections, ToManyInverseSideMappi
26622662
foreach ($found as $targetValue) {
26632663
$sourceEntity = $targetProperty->getValue($targetValue);
26642664

2665-
$id = $this->identifierFlattener->flattenIdentifier($class, $class->getIdentifierValues($sourceEntity));
2665+
if ($sourceEntity === null && isset($targetClass->associationMappings[$mappedBy]['joinColumns'])) {
2666+
// case where the hydration $targetValue itself has not yet fully completed, for example
2667+
// in case a bi-directional association is being hydrated and deferring eager loading is
2668+
// not possible due to subclassing.
2669+
$data = $this->getOriginalEntityData($targetValue);
2670+
$id = [];
2671+
foreach ($targetClass->associationMappings[$mappedBy]['joinColumns'] as $joinColumn) {
2672+
$id[] = $data[$joinColumn['name']];
2673+
}
2674+
} else {
2675+
$id = $this->identifierFlattener->flattenIdentifier($class, $class->getIdentifierValues($sourceEntity));
2676+
}
2677+
26662678
$idHash = implode(' ', $id);
26672679

26682680
if ($mapping->indexBy !== null) {
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\Tests\Models\AbstractFetchEager;
6+
7+
use Doctrine\Common\Collections\ArrayCollection;
8+
use Doctrine\Common\Collections\Collection;
9+
use Doctrine\ORM\Mapping as ORM;
10+
11+
#[ORM\Entity]
12+
#[ORM\Table(name: 'abstract_fetch_eager_remote_control')]
13+
#[ORM\InheritanceType('SINGLE_TABLE')]
14+
#[ORM\DiscriminatorColumn(name: 'type', type: 'string')]
15+
#[ORM\DiscriminatorMap(['mobile' => 'MobileRemoteControl'])]
16+
abstract class AbstractRemoteControl
17+
{
18+
#[ORM\Id]
19+
#[ORM\GeneratedValue]
20+
#[ORM\Column(type: 'integer')]
21+
public int $id;
22+
23+
#[ORM\Column(type: 'string')]
24+
public string $name;
25+
26+
/** @var Collection<User> */
27+
#[ORM\OneToMany(targetEntity: User::class, mappedBy: 'remoteControl', fetch: 'EAGER')]
28+
public Collection $users;
29+
30+
public function __construct(string $name)
31+
{
32+
$this->name = $name;
33+
$this->users = new ArrayCollection();
34+
}
35+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\Tests\Models\AbstractFetchEager;
6+
7+
use Doctrine\ORM\Mapping as ORM;
8+
9+
#[ORM\Entity]
10+
class MobileRemoteControl extends AbstractRemoteControl
11+
{
12+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\Tests\Models\AbstractFetchEager;
6+
7+
use Doctrine\ORM\Mapping as ORM;
8+
9+
#[ORM\Entity]
10+
#[ORM\Table(name: 'abstract_fetch_eager_user')]
11+
class User
12+
{
13+
#[ORM\Id]
14+
#[ORM\GeneratedValue]
15+
#[ORM\Column(type: 'integer')]
16+
public int $id;
17+
18+
#[ORM\ManyToOne(targetEntity: AbstractRemoteControl::class, inversedBy: 'users')]
19+
#[ORM\JoinColumn(nullable: false)]
20+
public AbstractRemoteControl $remoteControl;
21+
22+
public function __construct(AbstractRemoteControl $control)
23+
{
24+
$this->remoteControl = $control;
25+
}
26+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\Tests\ORM\Functional;
6+
7+
use Doctrine\Tests\Models\AbstractFetchEager\AbstractRemoteControl;
8+
use Doctrine\Tests\Models\AbstractFetchEager\MobileRemoteControl;
9+
use Doctrine\Tests\Models\AbstractFetchEager\User;
10+
use Doctrine\Tests\OrmFunctionalTestCase;
11+
12+
final class AbstractFetchEagerTest extends OrmFunctionalTestCase
13+
{
14+
public function testWithAbstractFetchEager(): void
15+
{
16+
$this->createSchemaForModels(
17+
AbstractRemoteControl::class,
18+
User::class,
19+
);
20+
21+
$control = new MobileRemoteControl('smart');
22+
$user = new User($control);
23+
24+
$entityManage = $this->getEntityManager();
25+
26+
$entityManage->persist($control);
27+
$entityManage->persist($user);
28+
$entityManage->flush();
29+
$entityManage->clear();
30+
31+
$user = $entityManage->find(User::class, $user->id);
32+
33+
self::assertNotNull($user);
34+
self::assertEquals('smart', $user->remoteControl->name);
35+
self::assertTrue($user->remoteControl->users->contains($user));
36+
}
37+
}

0 commit comments

Comments
 (0)