8000 [DoctrineBridge] Improved performance of the EntityType when used wit… · symfony/symfony@b604eb7 · GitHub
[go: up one dir, main page]

Skip to content

Commit b604eb7

Browse files
committed
[DoctrineBridge] Improved performance of the EntityType when used with the "query_builder" option
1 parent db2ee54 commit b604eb7

File tree

3 files changed

+62
-9
lines changed

3 files changed

+62
-9
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/Type/EntityType.php

Lines changed: 36 additions & 9 deletions
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