1 | <?php |
||
15 | class Builder |
||
16 | { |
||
17 | /** |
||
18 | * @var Filterer |
||
19 | */ |
||
20 | protected $filterer; |
||
21 | |||
22 | /** |
||
23 | * @var Sorter |
||
24 | */ |
||
25 | protected $sorter; |
||
26 | |||
27 | /** |
||
28 | * @var Paginator |
||
29 | */ |
||
30 | protected $paginator; |
||
31 | |||
32 | /** |
||
33 | * @var string |
||
34 | */ |
||
35 | protected $fromAlias; |
||
36 | |||
37 | /** |
||
38 | * @var array |
||
39 | */ |
||
40 | protected $joins; |
||
41 | |||
42 | /** |
||
43 | * @var array |
||
44 | */ |
||
45 | protected $selectFieldsMap = []; |
||
46 | |||
47 | /** |
||
48 | * @var RequiredFieldsExtractor |
||
49 | */ |
||
50 | protected $requiredFieldsExtractor; |
||
51 | |||
52 | /** |
||
53 | * @var JoinGenerator |
||
54 | */ |
||
55 | protected $joinGenerator; |
||
56 | |||
57 | /** |
||
58 | * @var SelectGenerator |
||
59 | */ |
||
60 | protected $selectGenerator; |
||
61 | |||
62 | /** |
||
63 | * @var SearchTextFieldHandler |
||
64 | */ |
||
65 | protected $searchTextFieldHandler; |
||
66 | |||
67 | /** |
||
68 | * @var EntityManager |
||
69 | */ |
||
70 | private $entityManager; |
||
71 | |||
72 | /** |
||
73 | * @var DataSourceInterface |
||
74 | */ |
||
75 | private $dataSource; |
||
76 | |||
77 | /** |
||
78 | * @param DataSourceInterface $dataSource |
||
79 | * @param EntityManager $entityManager |
||
80 | */ |
||
81 | public function __construct(DataSourceInterface $dataSource, EntityManager $entityManager) |
||
97 | |||
98 | /** |
||
99 | * Gets the fully generated query builder. Will autogenerate select and |
||
100 | * join statements as needed. |
||
101 | * |
||
102 | * This function is cached, and will only be generated once per execution. |
||
103 | * |
||
104 | * @param Query $query |
||
105 | * |
||
106 | * @return QueryBuilder |
||
107 | */ |
||
108 | public function buildQueryBuilder(Query $query, $entityClass) |
||
109 | { |
||
110 | $this->searchTextFieldHandler->handle($query->getFilter(), $this->dataSource->getFields()); |
||
111 | |||
112 | $queryBuilder = $this->entityManager->createQueryBuilder(); |
||
113 | $queryBuilder->from($entityClass, $this->getFromAlias()); |
||
114 | |||
115 | $select = $this->selectGenerator->generate($query); |
||
116 | $event = new GenerateSelectsEvent($select, $this->getFromAlias()); |
||
117 | $this->dataSource->getEventDispatcher()->dispatch(DoctrineDriver::EVENT_GENERATE_SELECTS, $event); |
||
118 | $select = $event->select; |
||
119 | $queryBuilder->add('select', $select); |
||
120 | |||
121 | $joins = $this->joinGenerator->generate($query); |
||
122 | $event = new GenerateJoinsEvent($this->getFromAlias(), $joins); |
||
123 | $this->dataSource->getEventDispatcher()->dispatch(DoctrineDriver::EVENT_GENERATE_JOINS, $event); |
||
124 | $joins = $event->joins; |
||
125 | foreach ($joins as $join) { |
||
126 | $queryBuilder |
||
127 | ->leftJoin($join->getJoin(), $join->getAlias(), $join->getConditionType(), $join->getCondition(), $join->getIndexBy()); |
||
128 | } |
||
129 | |||
130 | $this->filterer->filter($queryBuilder, $query->getFilter(), $this->selectGenerator->getUniqueNameToSelectFieldMap($query)); |
||
131 | |||
132 | $this->sorter->sort($queryBuilder, $query->getSort(), $this->selectGenerator->getUniqueNameToSelectFieldMap($query)); |
||
133 | |||
134 | $this->paginator->paginate($queryBuilder, $query->getPagination(), $this->dataSource->getFields()); |
||
135 | |||
136 | $this->dataSource->getEventDispatcher()->dispatch(DoctrineDriver::EVENT_POST_GENERATE_QUERY_BUILDER, new PostGenerateQueryBuilderEvent($queryBuilder, $this->getFromAlias())); |
||
137 | |||
138 | return $queryBuilder; |
||
139 | } |
||
140 | |||
141 | /** |
||
142 | * Gets the FROM alias, an internal name given to the class in the FROM part of the DQL. |
||
143 | * |
||
144 | * This name is generated once, and it's unique per execution of the data source. |
||
145 | * |
||
146 | * @return string |
||
147 | */ |
||
148 | protected function getFromAlias() |
||
156 | } |
||
157 |
The
EntityManager
might become unusable for example if a transaction is rolled back and it gets closed. Let’s assume that somewhere in your application, or in a third-party library, there is code such as the following:If that code throws an exception and the
EntityManager
is closed. Any other code which depends on the same instance of theEntityManager
during this request will fail.On the other hand, if you instead inject the
ManagerRegistry
, thegetManager()
method guarantees that you will always get a usable manager instance.