Skip to content

Commit abcad6f

Browse files
authored
Merge pull request #11090 from dbannik/2.17.x-failed-getting-entity-with-fetch-eager
[2.17.x] Failed getting entity with fetch eager property
2 parents 94d45a0 + 1b6cf58 commit abcad6f

File tree

5 files changed

+150
-1
lines changed

5 files changed

+150
-1
lines changed

Diff for: src/UnitOfWork.php

+13-1
Original file line numberDiff line numberDiff line change
@@ -3249,7 +3249,19 @@ private function eagerLoadCollections(array $collections, array $mapping): void
32493249
foreach ($found as $targetValue) {
32503250
$sourceEntity = $targetProperty->getValue($targetValue);
32513251

3252-
$id = $this->identifierFlattener->flattenIdentifier($class, $class->getIdentifierValues($sourceEntity));
3252+
if ($sourceEntity === null && isset($targetClass->associationMappings[$mappedBy]['joinColumns'])) {
3253+
// case where the hydration $targetValue itself has not yet fully completed, for example
3254+
// in case a bi-directional association is being hydrated and deferring eager loading is
3255+
// not possible due to subclassing.
3256+
$data = $this->getOriginalEntityData($targetValue);
3257+
$id = [];
3258+
foreach ($targetClass->associationMappings[$mappedBy]['joinColumns'] as $joinColumn) {
3259+
$id[] = $data[$joinColumn['name']];
3260+
}
3261+
} else {
3262+
$id = $this->identifierFlattener->flattenIdentifier($class, $class->getIdentifierValues($sourceEntity));
3263+
}
3264+
32533265
$idHash = implode(' ', $id);
32543266

32553267
if (isset($mapping['indexBy'])) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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+
/**
12+
* @ORM\Entity()
13+
* @ORM\Table(name="abstract_fetch_eager_remote_control")
14+
* @ORM\InheritanceType("SINGLE_TABLE")
15+
* @ORM\DiscriminatorColumn(name="type", type="string")
16+
* @ORM\DiscriminatorMap({"mobile"="MobileRemoteControl"})
17+
*/
18+
abstract class AbstractRemoteControl
19+
{
20+
/**
21+
* @ORM\Id
22+
* @ORM\GeneratedValue
23+
* @ORM\Column(type="integer")
24+
*
25+
* @var int
26+
*/
27+
public $id;
28+
29+
/**
30+
* /**
31+
*
32+
* @ORM\Column(type="string")
33+
*
34+
* @var string
35+
*/
36+
public $name;
37+
38+
/**
39+
* @ORM\OneToMany(targetEntity="User", mappedBy="remoteControl", fetch="EAGER")
40+
*
41+
* @var Collection<User>
42+
*/
43+
public $users;
44+
45+
public function __construct(string $name)
46+
{
47+
$this->name = $name;
48+
$this->users = new ArrayCollection();
49+
}
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
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+
/**
10+
* @ORM\Entity()
11+
*/
12+
class MobileRemoteControl extends AbstractRemoteControl
13+
{
14+
}

Diff for: tests/Tests/Models/AbstractFetchEager/User.php

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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+
/**
10+
* @ORM\Entity()
11+
* @ORM\Table(name="abstract_fetch_eager_user")
12+
*/
13+
class User
14+
{
15+
/**
16+
* @ORM\Id
17+
* @ORM\GeneratedValue
18+
* @ORM\Column(type="integer")
19+
*
20+
* @var int
21+
*/
22+
public $id;
23+
24+
/**
25+
* @ORM\ManyToOne(targetEntity="AbstractRemoteControl", inversedBy="users")
26+
* @ORM\JoinColumn(nullable=false)
27+
*
28+
* @var AbstractRemoteControl
29+
*/
30+
public $remoteControl;
31+
32+
public function __construct(AbstractRemoteControl $control)
33+
{
34+
$this->remoteControl = $control;
35+
}
36+
}
+37
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)