@@ -89,6 +89,24 @@ public static function createChoiceName($choice, $key, $value)
89
89
{
90
90
return (string ) $ value ;
91
91
}
92
+
93
+ /**
94
+ * Gets important parts from QueryBuilder that will allow to cache its results.
95
+ * For instance in ORM two query builders with an equal SQL string and
96
+ * equal parameters are considered to be equal.
97
+ *
98
+ * @param object $queryBuilder
99
+ *
100
+ * @return array|false Array with important QueryBuilder parts or false if
101
+ * they can't be determined
102
+ *
103
+ * @internal This method is public to be usable as callback. It should not
104
+ * be used in user code.
105
+ */
106
+ public function getQueryBuilderPartsForCachingHash ($ queryBuilder )
107
+ {
108
+ return false ;
109
+ }
92
110
93
111
public function __construct (ManagerRegistry $ registry , PropertyAccessorInterface $ propertyAccessor = null , ChoiceListFactoryInterface $ choiceListFactory = null )
94
112
{
@@ -115,29 +133,28 @@ public function configureOptions(OptionsResolver $resolver)
115
133
$ type = $ this ;
116
134
117
135
$ choiceLoader = function (Options $ options ) use ($ choiceListFactory , &$ choiceLoaders , $ type ) {
118
- // This closure and the "query_builder" options should be pushed to
119
- // EntityType in Symfony 3.0 as they are specific to the ORM
120
136
121
137
// Unless the choices are given explicitly, load them on demand
122
138
if (null === $ options ['choices ' ]) {
123
- // We consider two query builders with an equal SQL string and
124
- // equal parameters to be equal
125
- $ qbParts = $ options ['query_builder ' ] instanceof \Doctrine \ORM \QueryBuilder
126
- ? array (
127
- $ options ['query_builder ' ]->getQuery ()->getSQL (),
128
- $ options ['query_builder ' ]->getParameters ()->toArray (),
129
- )
130
- : null ;
131
-
132
- $ hash = CachingFactoryDecorator::generateHash (array (
133
- $ options ['em ' ],
134
- $ options ['class ' ],
135
- $ qbParts ,
136
- $ options ['loader ' ],
137
- ));
138
-
139
- if (isset ($ choiceLoaders [$ hash ])) {
140
- return $ choiceLoaders [$ hash ];
139
+
140
+ $ hash = null ;
141
+ $ qbParts = null ;
142
+
143
+ // If there is no QueryBuilder we can safely cache DoctrineChoiceLoader,
144
+ // also if concrete Type can return important QueryBuilder parts to generate
145
+ // hash key we go for it as well
146
+ if (!$ options ['query_builder ' ] || false !== ($ qbParts = $ type ->getQueryBuilderPartsForCachingHash ($ options ['query_builder ' ]))) {
147
+
148
+ $ hash = CachingFactoryDecorator::generateHash (array (
149
+ $ options ['em ' ],
150
+ $ options ['class ' ],
151
+ $ qbParts ,
152
+ $ options ['loader ' ],
153
+ ));
154
+
155
+ if (isset ($ choiceLoaders [$ hash ])) {
156
+ return $ choiceLoaders [$ hash ];
157
+ }
141
158
}
142
159
143
160
if ($ options ['loader ' ]) {
@@ -149,15 +166,19 @@ public function configureOptions(OptionsResolver $resolver)
149
166
$ entityLoader = $ type ->getLoader ($ options ['em ' ], $ queryBuilder , $ options ['class ' ]);
150
167
}
151
168
152
- $ choiceLoaders [ $ hash ] = new DoctrineChoiceLoader (
169
+ $ doctrineChoiceLoader = new DoctrineChoiceLoader (
153
170
$ choiceListFactory ,
154
171
$ options ['em ' ],
155
172
$ options ['class ' ],
156
173
$ options ['id_reader ' ],
157
174
$ entityLoader
158
175
);
176
+
177
+ if ($ hash !== null ) {
178
+ $ choiceLoaders [$ hash ] = $ doctrineChoiceLoader ;
179
+ }
159
180
160
- return $ choiceLoaders [ $ hash ] ;
181
+ return $ doctrineChoiceLoader ;
161
182
}
162
183
};
163
184
0 commit comments