8000 merged branch bschussek/issue6141 (PR #6206) · symfony/symfony@6be1d29 · GitHub
[go: up one dir, main page]

Skip to content

Commit 6be1d29

Browse files
committed
merged branch bschussek/issue6141 (PR #6206)
This PR was merged into the 2.1 branch. Commits ------- b604eb7 [DoctrineBridge] Improved performance of the EntityType when used with the "query_builder" option db2ee54 [DoctrineBridge] Improved exception message 99321cb [DoctrineBridge] Fixed: Exception is thrown if the entity class is not known to Doctrine Discussion ---------- [DoctrineBridge] fixed caching when EntityType is used with the "query_builder" option Bug fix: yes Feature addition: no Backwards compatibility break: no Symfony2 tests pass: yes Fixes the following tickets: - Todo: - License of the code: MIT Documentation PR: -
2 parents 101f042 + b604eb7 commit 6be1d29

File tree

5 files changed

+78
-11
lines changed

5 files changed

+78
-11
lines changed

src/Symfony/Bridge/Doctrine/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
2.1.5
5+
-----
6+
7+
* fixed caching of choice lists when EntityType is used with the "query_builder" option
8+
49
2.1.0
510
-----
611

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,10 @@ private function load()
392392
private function getIdentifierValues($entity)
393393
{
394394
if (!$this->em->contains($entity)) {
8000 395-
throw new FormException('Entities passed to the choice field must be managed');
395+
throw new FormException(
396+
'Entities passed to the choice field must be managed. Maybe ' .
397+
'persist them in the entity manager?'
398+
);
396399
}
397400

398401
$this->em->initializeObject($entity);

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Bridge\Doctrine\Form\Type;
1313

1414
use Doctrine\Common\Persistence\ManagerRegistry;
15+
use Symfony\Component\Form\Exception\FormException;
1516
use Doctrine\Common\Persistence\ObjectManager;
1617
use Symfony\Component\Form\FormBuilderInterface;
1718
use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityChoiceList;
@@ -130,7 +131,17 @@ public function setDefaultOptions(OptionsResolverInterface $resolver)
8000
130131
return $registry->getManager($em);
131132
}
132133

133-
return $registry->getManagerForClass($options['class']);
134+
$em = $registry->getManagerForClass($options['class']);
135+
136+
if (null === $em) {
137+
throw new FormException(sprintf(
138+
'Class "%s" seems not to be a managed Doctrine entity. ' .
139+
'Did you forget to map it?',
140+
$options['class']
141+
));
142+
}
143+
144+
return $em;
134145
};
135146

136147
$resolver->setDefaults(array(

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

Lines changed: 36 additions & 9 deletions
< 8000 div class="border position-relative rounded-bottom-2">
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,53 @@
1111

1212
namespace Symfony\Bridge\Doctrine\Form\Type;
1313

14-
use Doctrine\Common\Persistence\ObjectManager;
14+
use Symfony\Component\Form\Exception\UnexpectedTypeException;
1515
use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader;
16+
use Doctrine\Common\Persistence\ObjectManager;
17+
use Doctrine\ORM\QueryBuilder;
1618

1719
class EntityType extends DoctrineType
1820
{
21+
/**
22+
* @var array
23+
*/
24+
private $loaderCache = array();
25+
1926
/**
2027
* Return the default loader object.
2128
*
22-
* @param ObjectManager $manager
23-
* @param mixed $queryBuilder
24-
* @param string $class
29+
* @param ObjectManager $manager
30+
* @param QueryBuilder|\Closure $queryBuilder
31+
* @param string $class
32+
*
2533
* @return ORMQueryBuilderLoader
34+
*
35+
* @throws UnexpectedTypeException If the passed $queryBuilder is no \Closure
36+
* and no QueryBuilder or if the closure
37+
* does not return a QueryBuilder.
2638
*/
2739
public function getLoader(ObjectManager $manager, $queryBuilder, $class)
2840
{
29-
return new ORMQueryBuilderLoader(
30-
$queryBuilder,
31-
$manager,
32-
$class
33-
);
41+
if ($queryBuilder instanceof \Closure) {
42+
$queryBuilder = $queryBuilder($manager->getRepository($class));
43+
44+
if (!$queryBuilder instanceof QueryBuilder) {
45+
throw new UnexpectedTypeException($queryBuilder, 'Doctrine\ORM\QueryBuilder');
46+
}
47+
} elseif (!$queryBuilder instanceof QueryBuilder) {
48+
throw new UnexpectedTypeException($queryBuilder, 'Doctrine\ORM\QueryBuilder or \Closure');
49+
}
50+
51+
// It is important to return the same loader for identical queries,
52+
// otherwise the caching mechanism in DoctrineType does not work
53+
// (which expects identical loaders for the cache to work)
54+
$hash = md5($queryBuilder->getQuery()->getDQL());
55+
56+
if (!isset($this->loaderCache[$hash])) {
57+
$this->loaderCache[$hash] = new ORMQueryBuilderLoader($queryBuilder);
58+
}
59+
60+
return $this->loaderCache[$hash];
3461
}
3562

3663
public function getName()

src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypePerformanceTest.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Bridge\Doctrine\Tests\Form\Type;
1313

1414
use Symfony\Component\Form\Tests\FormPerformanceTestCase;
15+
use Doctrine\ORM\EntityRepository;
1516
use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIdentEntity;
1617
use Doctrine\ORM\Tools\SchemaTool;
1718
use Symfony\Bridge\Doctrine\Tests\DoctrineOrmTestCase;
@@ -36,6 +37,9 @@ protected function getExtensions()
3637
$manager->expects($this->any())
3738
->method('getManager')
3839
->will($this->returnValue($this->em));
40+
$manager->expects($this->any())
41+
->method('getManagerForClass')
42+
->will($this->returnValue($this->em));
3943

4044
return array(
4145
new CoreExtension(),
@@ -109,4 +113,21 @@ public function testCollapsedEntityField()
109113
$form->createView();
110114
}
111115
}
116+
117+
public function testCollapsedEntityFieldWithQueryBuilder()
118+
{
119+
$this->setMaxRunningTime(1);
120+
121+
for ($i = 0; $i < 20; ++$i) {
122+
$form = $this->factory->create('entity', null, array(
123+
'class' => self::ENTITY_CLASS,
124+
'query_builder' => function (EntityRepository $repo) {
125+
return $repo->createQueryBuilder('e')->addOrderBy('e.id', 'DESC');
126+
}
127+
));
128+
129+
// force loading of the choice list
130+
$form->createView();
131+
}
132+
}
112133
}

0 commit comments

Comments
 (0)
0