Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 764599b

Browse files
committed
[DoctrineBridge] Deprecated implicit optimization in DoctrineChoiceLoader
1 parent 50c22b3 commit 764599b

File tree

4 files changed

+98
-8
lines changed

4 files changed

+98
-8
lines changed

src/Symfony/Bridge/Doctrine/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ CHANGELOG
55
-----
66

77
* changed guessing of DECIMAL to set the `input` option of `NumberType` to string
8+
* deprecated not passing an `IdReader` to the `DoctrineChoiceLoader` when query can be optimized with a single id field
89

910
4.2.0
1011
-----

src/Symfony/Bridge/Doctrine/Form/ChoiceList/DoctrineChoiceLoader.php

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,29 @@ class DoctrineChoiceLoader implements ChoiceLoaderInterface
4040
* passed which optimizes the object loading for one of the Doctrine
4141
* mapper implementations.
4242
*
43-
* @param ObjectManager $manager The object manager
44-
* @param string $class The class name of the loaded objects
45-
* @param IdReader $idReader The reader for the object IDs
46-
* @param EntityLoaderInterface|null $objectLoader The objects loader
43+
* @param ObjectManager $manager The object manager
44+
* @param string $class The class name of the loaded objects
45+
* @param IdReader $idReader The reader for the object IDs
46+
* @param EntityLoaderInterface|null $objectLoader The objects loader
47+
* @param bool $checkOptimization For BC, to be removed in 5.0
4748
*/
48-
public function __construct(ObjectManager $manager, string $class, IdReader $idReader = null, EntityLoaderInterface $objectLoader = null)
49+
public function __construct(ObjectManager $manager, string $class, IdReader $idReader = null, EntityLoaderInterface $objectLoader = null, bool $checkOptimization = true)
4950
{
5051
$classMetadata = $manager->getClassMetadata($class);
5152

53+
if ($checkOptimization && null === $idReader) {
54+
$idReader = new IdReader($manager, $classMetadata);
55+
56+
if ($idReader->isSingleId()) {
57+
@trigger_error(sprintf('Not explicitly passing an instance of "%s" when it can optimize single id entity "%s" has been deprecated in 4.3 and will not apply any optimization in 5.0.', IdReader::class, $class), E_USER_DEPRECATED);
58+
} else {
59+
$idReader = null;
60+
}
61+
}
62+
5263
$this->manager = $manager;
5364
$this->class = $classMetadata->getName();
54-
$this->idReader = $idReader ?: new IdReader($manager, $classMetadata);
65+
$this->idReader = $idReader;
5566
$this->objectLoader = $objectLoader;
5667
}
5768

@@ -120,7 +131,7 @@ public function loadChoicesForValues(array $values, $value = null)
120131

121132
// Optimize performance in case we have an object loader and
122133
// a single-field identifier
123-
$optimize = null === $value || \is_array($value) && $this->idReader === $value[0];
134+
$optimize = $this->idReader && (null === $value || \is_array($value) && $this->idReader === $value[0]);
124135

125136
if ($optimize && !$this->choiceList && $this->objectLoader && $this->idReader->isSingleId()) {
126137
$unorderedObjects = $this->objectLoader->getEntitiesByIds($this->idReader->getIdField(), $values);

src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,8 @@ public function configureOptions(OptionsResolver $resolver)
150150
$options['em'],
151151
$options['class'],
152152
$options['id_reader'],
153-
$entityLoader
153+
$entityLoader,
154+
false
154155
);
155156

156157
if (null !== $hash) {

src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/DoctrineChoiceLoaderTest.php

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use Symfony\Bridge\Doctrine\Form\ChoiceList\DoctrineChoiceLoader;
1919
use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityLoaderInterface;
2020
use Symfony\Bridge\Doctrine\Form\ChoiceList\IdReader;
21+
use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity;
2122
use Symfony\Component\Form\ChoiceList\ArrayChoiceList;
2223
use Symfony\Component\Form\ChoiceList\Factory\ChoiceListFactoryInterface;
2324

@@ -393,4 +394,80 @@ public function testLoadChoicesForValuesLoadsOnlyChoicesIfValueIsIdReader()
393394

394395
$this->assertSame([$this->obj2], $loader->loadChoicesForValues(['2'], $value));
395396
}
397+
398+
/**
399+
* @group legacy
400+
*
401+
* @expectedDeprecation Not explicitly passing an instance of "Symfony\Bridge\Doctrine\Form\ChoiceList\IdReader" when it can optimize single id entity "%s" has been deprecated in 4.3 and will not apply any optimization in 5.0.
402+
*/
403+
public function testLoaderWithoutIdReaderCanBeOptimized()
404+
{
405+
$obj1 = new SingleIntIdEntity('1', 'one');
406+
$obj2 = new SingleIntIdEntity('2', 'two');
407+
408+
$metadata = $this->createMock(ClassMetadata::class);
409+
$metadata->expects($this->once())
410+
->method('getIdentifierFieldNames')
411+
->willReturn(['idField'])
412+
;
413+
$metadata->expects($this->any())
414+
->method('getIdentifierValues')
415+
->willReturnCallback(function ($obj) use ($obj1, $obj2) {
416+
if ($obj === $obj1) {
417+
return ['idField' => '1'];
418+
}
419+
if ($obj === $obj2) {
420+
return ['idField' => '2'];
421+
}
422+
423+
return null;
424+
})
425+
;
426+
427+
$this->om = $this->createMock(ObjectManager::class);
428+
$this->om->expects($this->once())
429+
->method('getClassMetadata')
430+
->with(SingleIntIdEntity::class)
431+
->willReturn($metadata)
432+
;
433+
$this->om->expects($this->any())
434+
->method('contains')
435+
->with($this->isInstanceOf(SingleIntIdEntity::class))
436+
->willReturn(true)
437+
;
438+
439+
$loader = new DoctrineChoiceLoader(
440+
$this->om,
441+
SingleIntIdEntity::class,
442+
null,
443+
$this->objectLoader
444+
);
445+
446+
$choices = [$obj1, $obj2];
447+
448+
$this->idReader->expects($this->any())
449+
->method('isSingleId')
450+
->willReturn(true);
451+
452+
$this->idReader->expects($this->any())
453+
->method('getIdField')
454+
->willReturn('idField');
455+
456+
$this->repository->expects($this->never())
457+
->method('findAll');
458+
459+
$this->objectLoader->expects($this->once())
460+
->method('getEntitiesByIds')
461+
->with('idField', ['1'])
462+
->willReturn($choices);
463+
464+
$this->idReader->expects($this->any())
465+
->method('getIdValue')
466+
->willReturnMap([
467+
[$obj1, '1'],
468+
[$obj2, '2'],
469+
]);
470+
471+
$this->assertSame([$obj1], $loader->loadChoicesForValues(['1']));
472+
}
396473
}

0 commit comments

Comments
 (0)