Skip to content

Commit ec7e38b

Browse files
authored
Merge pull request #1551 from dunglas/skip-extra-lazy
Always skip eager loading of collections marked as extra lazy
2 parents 98b9a02 + e1244e0 commit ec7e38b

File tree

2 files changed

+66
-25
lines changed

2 files changed

+66
-25
lines changed

src/Bridge/Doctrine/Orm/Extension/EagerLoadingExtension.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,12 @@ private function joinRelations(QueryBuilder $queryBuilder, QueryNameGeneratorInt
132132
continue;
133133
}
134134

135-
// We don't want to interfere with doctrine on this association
136-
if (false === $forceEager && ClassMetadataInfo::FETCH_EAGER !== $mapping['fetch']) {
135+
if (
136+
// Always skip extra lazy associations
137+
ClassMetadataInfo::FETCH_EXTRA_LAZY === $mapping['fetch'] ||
138+
// We don't want to interfere with doctrine on this association
139+
(false === $forceEager && ClassMetadataInfo::FETCH_EAGER !== $mapping['fetch'])
140+
) {
137141
continue;
138142
}
139143

tests/Bridge/Doctrine/Orm/Extension/EagerLoadingExtensionTest.php

Lines changed: 60 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\UnknownDummy;
3333
use Doctrine\ORM\EntityManager;
3434
use Doctrine\ORM\Mapping\ClassMetadata;
35+
use Doctrine\ORM\Mapping\ClassMetadataInfo;
3536
use Doctrine\ORM\QueryBuilder;
3637
use PHPUnit\Framework\TestCase;
3738
use Prophecy\Argument;
@@ -89,8 +90,8 @@ public function testApplyToCollection()
8990

9091
$classMetadataProphecy = $this->prophesize(ClassMetadata::class);
9192
$classMetadataProphecy->associationMappings = [
92-
'relatedDummy' => ['fetch' => 3, 'joinColumns' => [['nullable' => true]], 'targetEntity' => RelatedDummy::class],
93-
'relatedDummy2' => ['fetch' => 3, 'joinColumns' => [['nullable' => false]], 'targetEntity' => RelatedDummy::class],
93+
'relatedDummy' => ['fetch' => ClassMetadataInfo::FETCH_EAGER, 'joinColumns' => [['nullable' => true]], 'targetEntity' => RelatedDummy::class],
94+
'relatedDummy2' => ['fetch' => ClassMetadataInfo::FETCH_EAGER, 'joinColumns' => [['nullable' => false]], 'targetEntity' => RelatedDummy::class],
9495
];
9596

9697
$relatedClassMetadataProphecy = $this->prophesize(ClassMetadata::class);
@@ -171,12 +172,12 @@ public function testApplyToItem()
171172

172173
$classMetadataProphecy = $this->prophesize(ClassMetadata::class);
173174
$classMetadataProphecy->associationMappings = [
174-
'relatedDummy' => ['fetch' => 3, 'joinColumns' => [['nullable' => true]], 'targetEntity' => RelatedDummy::class],
175-
'relatedDummy2' => ['fetch' => 3, 'joinColumns' => [['nullable' => false]], 'targetEntity' => UnknownDummy::class],
176-
'relatedDummy3' => ['fetch' => 3, 'joinTable' => ['joinColumns' => [['nullable' => false]]], 'targetEntity' => UnknownDummy::class],
177-
'relatedDummy4' => ['fetch' => 3, 'targetEntity' => UnknownDummy::class],
178-
'relatedDummy5' => ['fetch' => 2, 'targetEntity' => UnknownDummy::class],
179-
'singleInheritanceRelation' => ['fetch' => 3, 'targetEntity' => AbstractDummy::class],
175+
'relatedDummy' => ['fetch' => ClassMetadataInfo::FETCH_EAGER, 'joinColumns' => [['nullable' => true]], 'targetEntity' => RelatedDummy::class],
176+
'relatedDummy2' => ['fetch' => ClassMetadataInfo::FETCH_EAGER, 'joinColumns' => [['nullable' => false]], 'targetEntity' => UnknownDummy::class],
177+
'relatedDummy3' => ['fetch' => ClassMetadataInfo::FETCH_EAGER, 'joinTable' => ['joinColumns' => [['nullable' => false]]], 'targetEntity' => UnknownDummy::class],
178+
'relatedDummy4' => ['fetch' => ClassMetadataInfo::FETCH_EAGER, 'targetEntity' => UnknownDummy::class],
179+
'relatedDummy5' => ['fetch' => ClassMetadataInfo::FETCH_LAZY, 'targetEntity' => UnknownDummy::class],
180+
'singleInheritanceRelation' => ['fetch' => ClassMetadataInfo::FETCH_EAGER, 'targetEntity' => AbstractDummy::class],
180181
];
181182

182183
$relatedClassMetadataProphecy = $this->prophesize(ClassMetadata::class);
@@ -189,7 +190,7 @@ public function testApplyToItem()
189190
$relatedClassMetadataProphecy->hasField('embeddedDummy.name')->willReturn(true)->shouldBeCalled();
190191

191192
$relatedClassMetadataProphecy->associationMappings = [
192-
'relation' => ['fetch' => 3, 'joinColumns' => [['nullable' => false]], 'targetEntity' => UnknownDummy::class],
193+
'relation' => ['fetch' => ClassMetadataInfo::FETCH_EAGER, 'joinColumns' => [['nullable' => false]], 'targetEntity' => UnknownDummy::class],
193194
];
194195

195196
$relatedClassMetadataProphecy->embeddedClasses = ['embeddedDummy' => ['class' => EmbeddableDummy::class]];
@@ -349,12 +350,12 @@ public function testMaxJoinsReached()
349350

350351
$classMetadataProphecy = $this->prophesize(ClassMetadata::class);
351352
$classMetadataProphecy->associationMappings = [
352-
'relatedDummy' => ['fetch' => 3, 'joinColumns' => [['nullable' => false]], 'targetEntity' => RelatedDummy::class],
353+
'relatedDummy' => ['fetch' => ClassMetadataInfo::FETCH_EAGER, 'joinColumns' => [['nullable' => false]], 'targetEntity' => RelatedDummy::class],
353354
];
354355

355356
$relatedClassMetadataProphecy = $this->prophesize(ClassMetadata::class);
356357
$relatedClassMetadataProphecy->associationMappings = [
357-
'dummy' => ['fetch' => 3, 'joinColumns' => [['nullable' => false]], 'targetEntity' => Dummy::class],
358+
'dummy' => ['fetch' => ClassMetadataInfo::FETCH_EAGER, 'joinColumns' => [['nullable' => false]], 'targetEntity' => Dummy::class],
358359
];
359360

360361
$emProphecy = $this->prophesize(EntityManager::class);
@@ -401,12 +402,12 @@ public function testMaxDepth()
401402

402403
$classMetadataProphecy = $this->prophesize(ClassMetadata::class);
403404
$classMetadataProphecy->associationMappings = [
404-
'relatedDummy' => ['fetch' => 3, 'joinColumns' => [['nullable' => false]], 'targetEntity' => RelatedDummy::class],
405+
'relatedDummy' => ['fetch' => ClassMetadataInfo::FETCH_EAGER, 'joinColumns' => [['nullable' => false]], 'targetEntity' => RelatedDummy::class],
405406
];
406407

407408
$relatedClassMetadataProphecy = $this->prophesize(ClassMetadata::class);
408409
$relatedClassMetadataProphecy->associationMappings = [
409-
'dummy' => ['fetch' => 3, 'joinColumns' => [['nullable' => false]], 'targetEntity' => Dummy::class],
410+
'dummy' => ['fetch' => ClassMetadataInfo::FETCH_EAGER, 'joinColumns' => [['nullable' => false]], 'targetEntity' => Dummy::class],
410411
];
411412

412413
$dummyClassMetadataInterfaceProphecy = $this->prophesize(ClassMetadataInterface::class);
@@ -464,7 +465,7 @@ public function testForceEager()
464465

465466
$classMetadataProphecy = $this->prophesize(ClassMetadata::class);
466467
$classMetadataProphecy->associationMappings = [
467-
'relation' => ['fetch' => 2, 'targetEntity' => UnknownDummy::class, 'joinColumns' => [['nullable' => false]]],
468+
'relation' => ['fetch' => ClassMetadataInfo::FETCH_LAZY, 'targetEntity' => UnknownDummy::class, 'joinColumns' => [['nullable' => false]]],
468469
];
469470

470471
$unknownClassMetadataProphecy = $this->prophesize(ClassMetadata::class);
@@ -484,6 +485,42 @@ public function testForceEager()
484485
$orderExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, []);
485486
}
486487

488+
public function testExtraLazy()
489+
{
490+
$resourceMetadata = new ResourceMetadata();
491+
$resourceMetadata = $resourceMetadata->withAttributes(['normalization_context' => [AbstractNormalizer::GROUPS => 'foobar']]);
492+
$resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class);
493+
$resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($resourceMetadata);
494+
495+
$propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
496+
//$propertyNameCollectionFactoryProphecy->create(UnknownDummy::class)->willReturn(new PropertyNameCollection(['id']))->shouldBeCalled();
497+
498+
$propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
499+
$relationPropertyMetadata = new PropertyMetadata();
500+
$relationPropertyMetadata = $relationPropertyMetadata->withReadableLink(true);
501+
502+
$propertyMetadataFactoryProphecy->create(Dummy::class, 'relation', ['serializer_groups' => 'foobar'])->willReturn($relationPropertyMetadata)->shouldBeCalled();
503+
504+
$queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
505+
506+
$classMetadataProphecy = $this->prophesize(ClassMetadata::class);
507+
$classMetadataProphecy->associationMappings = [
508+
'relation' => ['fetch' => ClassMetadataInfo::FETCH_EXTRA_LAZY, 'targetEntity' => UnknownDummy::class, 'joinColumns' => [['nullable' => false]]],
509+
];
510+
511+
$unknownClassMetadataProphecy = $this->prophesize(ClassMetadata::class);
512+
$unknownClassMetadataProphecy->associationMappings = [];
513+
514+
$emProphecy = $this->prophesize(EntityManager::class);
515+
$emProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal());
516+
517+
$queryBuilderProphecy->getRootAliases()->willReturn(['o']);
518+
$queryBuilderProphecy->getEntityManager()->willReturn($emProphecy);
519+
520+
$orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true, null, null, true);
521+
$orderExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, []);
522+
}
523+
487524
public function testResourceClassNotFoundException()
488525
{
489526
$resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class);
@@ -496,7 +533,7 @@ public function testResourceClassNotFoundException()
496533

497534
$classMetadataProphecy = $this->prophesize(ClassMetadata::class);
498535
$classMetadataProphecy->associationMappings = [
499-
'relation' => ['fetch' => 2, 'targetEntity' => UnknownDummy::class, 'joinColumns' => [['nullable' => false]]],
536+
'relation' => ['fetch' => ClassMetadataInfo::FETCH_LAZY, 'targetEntity' => UnknownDummy::class, 'joinColumns' => [['nullable' => false]]],
500537
];
501538
$emProphecy = $this->prophesize(EntityManager::class);
502539
$emProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal());
@@ -520,7 +557,7 @@ public function testPropertyNotFoundException()
520557

521558
$classMetadataProphecy = $this->prophesize(ClassMetadata::class);
522559
$classMetadataProphecy->associationMappings = [
523-
'relation' => ['fetch' => 2, 'targetEntity' => UnknownDummy::class, 'joinColumns' => [['nullable' => false]]],
560+
'relation' => ['fetch' => ClassMetadataInfo::FETCH_LAZY, 'targetEntity' => UnknownDummy::class, 'joinColumns' => [['nullable' => false]]],
524561
];
525562
$emProphecy = $this->prophesize(EntityManager::class);
526563
$emProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal());
@@ -547,7 +584,7 @@ public function testResourceClassNotFoundExceptionPropertyNameCollection()
547584

548585
$classMetadataProphecy = $this->prophesize(ClassMetadata::class);
549586
$classMetadataProphecy->associationMappings = [
550-
'relation' => ['fetch' => 2, 'targetEntity' => UnknownDummy::class, 'joinColumns' => [['nullable' => false]]],
587+
'relation' => ['fetch' => ClassMetadataInfo::FETCH_LAZY, 'targetEntity' => UnknownDummy::class, 'joinColumns' => [['nullable' => false]]],
551588
];
552589
$emProphecy = $this->prophesize(EntityManager::class);
553590
$emProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal());
@@ -589,7 +626,7 @@ public function testApplyToCollectionWithSerializerContextBuilder()
589626

590627
$classMetadataProphecy = $this->prophesize(ClassMetadata::class);
591628
$classMetadataProphecy->associationMappings = [
592-
'relatedDummy' => ['fetch' => 3, 'joinColumns' => [['nullable' => true]], 'targetEntity' => RelatedDummy::class],
629+
'relatedDummy' => ['fetch' => ClassMetadataInfo::FETCH_EAGER, 'joinColumns' => [['nullable' => true]], 'targetEntity' => RelatedDummy::class],
593630
];
594631

595632
$relatedClassMetadataProphecy = $this->prophesize(ClassMetadata::class);
@@ -653,7 +690,7 @@ public function testAttributes()
653690

654691
$classMetadataProphecy = $this->prophesize(ClassMetadata::class);
655692
$classMetadataProphecy->associationMappings = [
656-
'relatedDummy' => ['fetch' => 3, 'joinColumns' => [['nullable' => true]], 'targetEntity' => RelatedDummy::class],
693+
'relatedDummy' => ['fetch' => ClassMetadataInfo::FETCH_EAGER, 'joinColumns' => [['nullable' => true]], 'targetEntity' => RelatedDummy::class],
657694
];
658695

659696
$relatedClassMetadataProphecy = $this->prophesize(ClassMetadata::class);
@@ -707,8 +744,8 @@ public function testApplyToCollectionNoPartial()
707744

708745
$classMetadataProphecy = $this->prophesize(ClassMetadata::class);
709746
$classMetadataProphecy->associationMappings = [
710-
'relatedDummy' => ['fetch' => 3, 'joinColumns' => [['nullable' => true]], 'targetEntity' => RelatedDummy::class],
711-
'relatedDummy2' => ['fetch' => 3, 'joinColumns' => [['nullable' => false]], 'targetEntity' => RelatedDummy::class],
747+
'relatedDummy' => ['fetch' => ClassMetadataInfo::FETCH_EAGER, 'joinColumns' => [['nullable' => true]], 'targetEntity' => RelatedDummy::class],
748+
'relatedDummy2' => ['fetch' => ClassMetadataInfo::FETCH_EAGER, 'joinColumns' => [['nullable' => false]], 'targetEntity' => RelatedDummy::class],
712749
];
713750

714751
$emProphecy = $this->prophesize(EntityManager::class);
@@ -750,8 +787,8 @@ public function testApplyToCollectionWithANonRedableButFetchEagerProperty()
750787

751788
$classMetadataProphecy = $this->prophesize(ClassMetadata::class);
752789
$classMetadataProphecy->associationMappings = [
753-
'relatedDummy' => ['fetch' => 3, 'joinColumns' => [['nullable' => true]], 'targetEntity' => RelatedDummy::class],
754-
'relatedDummy2' => ['fetch' => 3, 'joinColumns' => [['nullable' => false]], 'targetEntity' => RelatedDummy::class],
790+
'relatedDummy' => ['fetch' => ClassMetadataInfo::FETCH_EAGER, 'joinColumns' => [['nullable' => true]], 'targetEntity' => RelatedDummy::class],
791+
'relatedDummy2' => ['fetch' => ClassMetadataInfo::FETCH_EAGER, 'joinColumns' => [['nullable' => false]], 'targetEntity' => RelatedDummy::class],
755792
];
756793

757794
$emProphecy = $this->prophesize(EntityManager::class);

0 commit comments

Comments
 (0)