ORMQueryBuilderLoader.php 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Bridge\Doctrine\Form\ChoiceList;
  11. use Doctrine\Common\Persistence\ObjectManager;
  12. use Doctrine\DBAL\Connection;
  13. use Doctrine\ORM\QueryBuilder;
  14. use Symfony\Component\Form\Exception\UnexpectedTypeException;
  15. /**
  16. * Loads entities using a {@link QueryBuilder} instance.
  17. *
  18. * @author Benjamin Eberlei <kontakt@beberlei.de>
  19. * @author Bernhard Schussek <bschussek@gmail.com>
  20. */
  21. class ORMQueryBuilderLoader implements EntityLoaderInterface
  22. {
  23. /**
  24. * Contains the query builder that builds the query for fetching the
  25. * entities.
  26. *
  27. * This property should only be accessed through queryBuilder.
  28. *
  29. * @var QueryBuilder
  30. */
  31. private $queryBuilder;
  32. /**
  33. * Construct an ORM Query Builder Loader.
  34. *
  35. * @param QueryBuilder|\Closure $queryBuilder The query builder or a closure
  36. * for creating the query builder.
  37. * Passing a closure is
  38. * deprecated and will not be
  39. * supported anymore as of
  40. * Symfony 3.0.
  41. * @param ObjectManager $manager Deprecated
  42. * @param string $class Deprecated
  43. *
  44. * @throws UnexpectedTypeException
  45. */
  46. public function __construct($queryBuilder, $manager = null, $class = null)
  47. {
  48. // If a query builder was passed, it must be a closure or QueryBuilder
  49. // instance
  50. if (!($queryBuilder instanceof QueryBuilder || $queryBuilder instanceof \Closure)) {
  51. throw new UnexpectedTypeException($queryBuilder, 'Doctrine\ORM\QueryBuilder or \Closure');
  52. }
  53. if ($queryBuilder instanceof \Closure) {
  54. @trigger_error('Passing a QueryBuilder closure to '.__CLASS__.'::__construct() is deprecated since Symfony 2.7 and will be removed in 3.0.', E_USER_DEPRECATED);
  55. if (!$manager instanceof ObjectManager) {
  56. throw new UnexpectedTypeException($manager, 'Doctrine\Common\Persistence\ObjectManager');
  57. }
  58. @trigger_error('Passing an EntityManager to '.__CLASS__.'::__construct() is deprecated since Symfony 2.7 and will be removed in 3.0.', E_USER_DEPRECATED);
  59. @trigger_error('Passing a class to '.__CLASS__.'::__construct() is deprecated since Symfony 2.7 and will be removed in 3.0.', E_USER_DEPRECATED);
  60. $queryBuilder = $queryBuilder($manager->getRepository($class));
  61. if (!$queryBuilder instanceof QueryBuilder) {
  62. throw new UnexpectedTypeException($queryBuilder, 'Doctrine\ORM\QueryBuilder');
  63. }
  64. }
  65. $this->queryBuilder = $queryBuilder;
  66. }
  67. /**
  68. * {@inheritdoc}
  69. */
  70. public function getEntities()
  71. {
  72. return $this->queryBuilder->getQuery()->execute();
  73. }
  74. /**
  75. * {@inheritdoc}
  76. */
  77. public function getEntitiesByIds($identifier, array $values)
  78. {
  79. $qb = clone $this->queryBuilder;
  80. $alias = current($qb->getRootAliases());
  81. $parameter = 'ORMQueryBuilderLoader_getEntitiesByIds_'.$identifier;
  82. $parameter = str_replace('.', '_', $parameter);
  83. $where = $qb->expr()->in($alias.'.'.$identifier, ':'.$parameter);
  84. // Guess type
  85. $entity = current($qb->getRootEntities());
  86. $metadata = $qb->getEntityManager()->getClassMetadata($entity);
  87. if (\in_array($metadata->getTypeOfField($identifier), array('integer', 'bigint', 'smallint'))) {
  88. $parameterType = Connection::PARAM_INT_ARRAY;
  89. // Filter out non-integer values (e.g. ""). If we don't, some
  90. // databases such as PostgreSQL fail.
  91. $values = array_values(array_filter($values, function ($v) {
  92. return (string) $v === (string) (int) $v || ctype_digit($v);
  93. }));
  94. } elseif (\in_array($metadata->getTypeOfField($identifier), array('uuid', 'guid'))) {
  95. $parameterType = Connection::PARAM_STR_ARRAY;
  96. // Like above, but we just filter out empty strings.
  97. $values = array_values(array_filter($values, function ($v) {
  98. return '' !== (string) $v;
  99. }));
  100. } else {
  101. $parameterType = Connection::PARAM_STR_ARRAY;
  102. }
  103. if (!$values) {
  104. return array();
  105. }
  106. return $qb->andWhere($where)
  107. ->getQuery()
  108. ->setParameter($parameter, $values, $parameterType)
  109. ->getResult();
  110. }
  111. }