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" optiondb2ee54
[DoctrineBridge] Improved exception message99321cb
[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: -
This commit is contained in:
commit
6be1d29a3d
@ -1,6 +1,11 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
2.1.5
|
||||
-----
|
||||
|
||||
* fixed caching of choice lists when EntityType is used with the "query_builder" option
|
||||
|
||||
2.1.0
|
||||
-----
|
||||
|
||||
|
@ -392,7 +392,10 @@ class EntityChoiceList extends ObjectChoiceList
|
||||
private function getIdentifierValues($entity)
|
||||
{
|
||||
if (!$this->em->contains($entity)) {
|
||||
throw new FormException('Entities passed to the choice field must be managed');
|
||||
throw new FormException(
|
||||
'Entities passed to the choice field must be managed. Maybe ' .
|
||||
'persist them in the entity manager?'
|
||||
);
|
||||
}
|
||||
|
||||
$this->em->initializeObject($entity);
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace Symfony\Bridge\Doctrine\Form\Type;
|
||||
|
||||
use Doctrine\Common\Persistence\ManagerRegistry;
|
||||
use Symfony\Component\Form\Exception\FormException;
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityChoiceList;
|
||||
@ -130,7 +131,17 @@ abstract class DoctrineType extends AbstractType
|
||||
return $registry->getManager($em);
|
||||
}
|
||||
|
||||
return $registry->getManagerForClass($options['class']);
|
||||
$em = $registry->getManagerForClass($options['class']);
|
||||
|
||||
if (null === $em) {
|
||||
throw new FormException(sprintf(
|
||||
'Class "%s" seems not to be a managed Doctrine entity. ' .
|
||||
'Did you forget to map it?',
|
||||
$options['class']
|
||||
));
|
||||
}
|
||||
|
||||
return $em;
|
||||
};
|
||||
|
||||
$resolver->setDefaults(array(
|
||||
|
@ -11,26 +11,53 @@
|
||||
|
||||
namespace Symfony\Bridge\Doctrine\Form\Type;
|
||||
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Symfony\Component\Form\Exception\UnexpectedTypeException;
|
||||
use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader;
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
|
||||
class EntityType extends DoctrineType
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $loaderCache = array();
|
||||
|
||||
/**
|
||||
* Return the default loader object.
|
||||
*
|
||||
* @param ObjectManager $manager
|
||||
* @param mixed $queryBuilder
|
||||
* @param string $class
|
||||
* @param ObjectManager $manager
|
||||
* @param QueryBuilder|\Closure $queryBuilder
|
||||
* @param string $class
|
||||
*
|
||||
* @return ORMQueryBuilderLoader
|
||||
*
|
||||
* @throws UnexpectedTypeException If the passed $queryBuilder is no \Closure
|
||||
* and no QueryBuilder or if the closure
|
||||
* does not return a QueryBuilder.
|
||||
*/
|
||||
public function getLoader(ObjectManager $manager, $queryBuilder, $class)
|
||||
{
|
||||
return new ORMQueryBuilderLoader(
|
||||
$queryBuilder,
|
||||
$manager,
|
||||
$class
|
||||
);
|
||||
if ($queryBuilder instanceof \Closure) {
|
||||
$queryBuilder = $queryBuilder($manager->getRepository($class));
|
||||
|
||||
if (!$queryBuilder instanceof QueryBuilder) {
|
||||
throw new UnexpectedTypeException($queryBuilder, 'Doctrine\ORM\QueryBuilder');
|
||||
}
|
||||
} elseif (!$queryBuilder instanceof QueryBuilder) {
|
||||
throw new UnexpectedTypeException($queryBuilder, 'Doctrine\ORM\QueryBuilder or \Closure');
|
||||
}
|
||||
|
||||
// It is important to return the same loader for identical queries,
|
||||
// otherwise the caching mechanism in DoctrineType does not work
|
||||
// (which expects identical loaders for the cache to work)
|
||||
$hash = md5($queryBuilder->getQuery()->getDQL());
|
||||
|
||||
if (!isset($this->loaderCache[$hash])) {
|
||||
$this->loaderCache[$hash] = new ORMQueryBuilderLoader($queryBuilder);
|
||||
}
|
||||
|
||||
return $this->loaderCache[$hash];
|
||||
}
|
||||
|
||||
public function getName()
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace Symfony\Bridge\Doctrine\Tests\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\Tests\FormPerformanceTestCase;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIdentEntity;
|
||||
use Doctrine\ORM\Tools\SchemaTool;
|
||||
use Symfony\Bridge\Doctrine\Tests\DoctrineOrmTestCase;
|
||||
@ -36,6 +37,9 @@ class EntityTypePerformanceTest extends FormPerformanceTestCase
|
||||
$manager->expects($this->any())
|
||||
->method('getManager')
|
||||
->will($this->returnValue($this->em));
|
||||
$manager->expects($this->any())
|
||||
->method('getManagerForClass')
|
||||
->will($this->returnValue($this->em));
|
||||
|
||||
return array(
|
||||
new CoreExtension(),
|
||||
@ -109,4 +113,21 @@ class EntityTypePerformanceTest extends FormPerformanceTestCase
|
||||
$form->createView();
|
||||
}
|
||||
}
|
||||
|
||||
public function testCollapsedEntityFieldWithQueryBuilder()
|
||||
{
|
||||
$this->setMaxRunningTime(1);
|
||||
|
||||
for ($i = 0; $i < 20; ++$i) {
|
||||
$form = $this->factory->create('entity', null, array(
|
||||
'class' => self::ENTITY_CLASS,
|
||||
'query_builder' => function (EntityRepository $repo) {
|
||||
return $repo->createQueryBuilder('e')->addOrderBy('e.id', 'DESC');
|
||||
}
|
||||
));
|
||||
|
||||
// force loading of the choice list
|
||||
$form->createView();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user