Complex classes like Query often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Query, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
40 | final class Query extends AbstractQuery |
||
41 | { |
||
42 | /** |
||
43 | * A query object is in CLEAN state when it has NO unparsed/unprocessed DQL parts. |
||
44 | */ |
||
45 | const STATE_CLEAN = 1; |
||
46 | |||
47 | /** |
||
48 | * A query object is in state DIRTY when it has DQL parts that have not yet been |
||
49 | * parsed/processed. This is automatically defined as DIRTY when addDqlQueryPart |
||
50 | * is called. |
||
51 | */ |
||
52 | const STATE_DIRTY = 2; |
||
53 | |||
54 | /* Query HINTS */ |
||
55 | |||
56 | /** |
||
57 | * The refresh hint turns any query into a refresh query with the result that |
||
58 | * any local changes in entities are overridden with the fetched values. |
||
59 | * |
||
60 | * @var string |
||
61 | */ |
||
62 | const HINT_REFRESH = 'doctrine.refresh'; |
||
63 | |||
64 | /** |
||
65 | * @var string |
||
66 | */ |
||
67 | const HINT_CACHE_ENABLED = 'doctrine.cache.enabled'; |
||
68 | |||
69 | /** |
||
70 | * @var string |
||
71 | */ |
||
72 | const HINT_CACHE_EVICT = 'doctrine.cache.evict'; |
||
73 | |||
74 | /** |
||
75 | * Internal hint: is set to the proxy entity that is currently triggered for loading |
||
76 | * |
||
77 | * @var string |
||
78 | */ |
||
79 | const HINT_REFRESH_ENTITY = 'doctrine.refresh.entity'; |
||
80 | |||
81 | /** |
||
82 | * The forcePartialLoad query hint forces a particular query to return |
||
83 | * partial objects. |
||
84 | * |
||
85 | * @var string |
||
86 | * @todo Rename: HINT_OPTIMIZE |
||
87 | */ |
||
88 | const HINT_FORCE_PARTIAL_LOAD = 'doctrine.forcePartialLoad'; |
||
89 | |||
90 | /** |
||
91 | * The includeMetaColumns query hint causes meta columns like foreign keys and |
||
92 | * discriminator columns to be selected and returned as part of the query result. |
||
93 | * |
||
94 | * This hint does only apply to non-object queries. |
||
95 | * |
||
96 | * @var string |
||
97 | */ |
||
98 | const HINT_INCLUDE_META_COLUMNS = 'doctrine.includeMetaColumns'; |
||
99 | |||
100 | /** |
||
101 | * An array of class names that implement \Doctrine\ORM\Query\TreeWalker and |
||
102 | * are iterated and executed after the DQL has been parsed into an AST. |
||
103 | * |
||
104 | * @var string |
||
105 | */ |
||
106 | const HINT_CUSTOM_TREE_WALKERS = 'doctrine.customTreeWalkers'; |
||
107 | |||
108 | /** |
||
109 | * A string with a class name that implements \Doctrine\ORM\Query\TreeWalker |
||
110 | * and is used for generating the target SQL from any DQL AST tree. |
||
111 | * |
||
112 | * @var string |
||
113 | */ |
||
114 | const HINT_CUSTOM_OUTPUT_WALKER = 'doctrine.customOutputWalker'; |
||
115 | |||
116 | //const HINT_READ_ONLY = 'doctrine.readOnly'; |
||
|
|||
117 | |||
118 | /** |
||
119 | * @var string |
||
120 | */ |
||
121 | const HINT_INTERNAL_ITERATION = 'doctrine.internal.iteration'; |
||
122 | |||
123 | /** |
||
124 | * @var string |
||
125 | */ |
||
126 | const HINT_LOCK_MODE = 'doctrine.lockMode'; |
||
127 | |||
128 | /** |
||
129 | * The current state of this query. |
||
130 | * |
||
131 | * @var integer |
||
132 | */ |
||
133 | private $_state = self::STATE_CLEAN; |
||
134 | |||
135 | /** |
||
136 | * A snapshot of the parameter types the query was parsed with. |
||
137 | * |
||
138 | * @var array |
||
139 | */ |
||
140 | private $_parsedTypes = []; |
||
141 | |||
142 | /** |
||
143 | * Cached DQL query. |
||
144 | * |
||
145 | * @var string |
||
146 | */ |
||
147 | private $_dql = null; |
||
148 | |||
149 | /** |
||
150 | * The parser result that holds DQL => SQL information. |
||
151 | * |
||
152 | * @var \Doctrine\ORM\Query\ParserResult |
||
153 | */ |
||
154 | private $_parserResult; |
||
155 | |||
156 | /** |
||
157 | * The first result to return (the "offset"). |
||
158 | * |
||
159 | * @var integer |
||
160 | */ |
||
161 | private $_firstResult = null; |
||
162 | |||
163 | /** |
||
164 | * The maximum number of results to return (the "limit"). |
||
165 | * |
||
166 | * @var integer|null |
||
167 | */ |
||
168 | private $_maxResults = null; |
||
169 | |||
170 | /** |
||
171 | * The cache driver used for caching queries. |
||
172 | * |
||
173 | * @var \Doctrine\Common\Cache\Cache|null |
||
174 | */ |
||
175 | private $_queryCache; |
||
176 | |||
177 | /** |
||
178 | * Whether or not expire the query cache. |
||
179 | * |
||
180 | * @var boolean |
||
181 | */ |
||
182 | private $_expireQueryCache = false; |
||
183 | |||
184 | /** |
||
185 | * The query cache lifetime. |
||
186 | * |
||
187 | * @var int |
||
188 | */ |
||
189 | private $_queryCacheTTL; |
||
190 | |||
191 | /** |
||
192 | * Whether to use a query cache, if available. Defaults to TRUE. |
||
193 | * |
||
194 | * @var boolean |
||
195 | */ |
||
196 | private $_useQueryCache = true; |
||
197 | |||
198 | /** |
||
199 | * Gets the SQL query/queries that correspond to this DQL query. |
||
200 | * |
||
201 | * @return mixed The built sql query or an array of all sql queries. |
||
202 | * |
||
203 | * @override |
||
204 | */ |
||
205 | 336 | public function getSQL() |
|
209 | |||
210 | /** |
||
211 | * Returns the corresponding AST for this DQL query. |
||
212 | * |
||
213 | * @return \Doctrine\ORM\Query\AST\SelectStatement | |
||
214 | * \Doctrine\ORM\Query\AST\UpdateStatement | |
||
215 | * \Doctrine\ORM\Query\AST\DeleteStatement |
||
216 | */ |
||
217 | 2 | public function getAST() |
|
223 | |||
224 | /** |
||
225 | * {@inheritdoc} |
||
226 | */ |
||
227 | 441 | protected function getResultSetMapping() |
|
236 | |||
237 | /** |
||
238 | * Parses the DQL query, if necessary, and stores the parser result. |
||
239 | * |
||
240 | * Note: Populates $this->_parserResult as a side-effect. |
||
241 | * |
||
242 | * @return \Doctrine\ORM\Query\ParserResult |
||
243 | */ |
||
244 | 762 | private function _parse() |
|
289 | |||
290 | /** |
||
291 | * {@inheritdoc} |
||
292 | */ |
||
293 | 458 | protected function _doExecute() |
|
294 | { |
||
295 | 458 | $executor = $this->_parse()->getSqlExecutor(); |
|
296 | |||
297 | 449 | if ($this->_queryCacheProfile) { |
|
298 | 8 | $executor->setQueryCacheProfile($this->_queryCacheProfile); |
|
299 | } else { |
||
300 | 443 | $executor->removeQueryCacheProfile(); |
|
301 | } |
||
302 | |||
303 | 449 | if ($this->_resultSetMapping === null) { |
|
304 | 407 | $this->_resultSetMapping = $this->_parserResult->getResultSetMapping(); |
|
305 | } |
||
306 | |||
307 | // Prepare parameters |
||
308 | 449 | $paramMappings = $this->_parserResult->getParameterMappings(); |
|
309 | 449 | $paramCount = count($this->parameters); |
|
310 | 449 | $mappingCount = count($paramMappings); |
|
311 | |||
312 | 449 | if ($paramCount > $mappingCount) { |
|
313 | 1 | throw QueryException::tooManyParameters($mappingCount, $paramCount); |
|
314 | } |
||
315 | |||
316 | 448 | if ($paramCount < $mappingCount) { |
|
317 | 1 | throw QueryException::tooFewParameters($mappingCount, $paramCount); |
|
318 | } |
||
319 | |||
320 | // evict all cache for the entity region |
||
321 | 447 | if ($this->hasCache && isset($this->_hints[self::HINT_CACHE_EVICT]) && $this->_hints[self::HINT_CACHE_EVICT]) { |
|
322 | 2 | $this->evictEntityCacheRegion(); |
|
323 | } |
||
324 | |||
325 | 447 | list($sqlParams, $types) = $this->processParameterMappings($paramMappings); |
|
326 | |||
327 | 446 | $this->evictResultSetCache( |
|
328 | 446 | $executor, |
|
329 | 446 | $sqlParams, |
|
330 | 446 | $types, |
|
331 | 446 | $this->_em->getConnection()->getParams() |
|
332 | ); |
||
333 | |||
334 | 446 | return $executor->execute($this->_em->getConnection(), $sqlParams, $types); |
|
335 | } |
||
336 | |||
337 | 446 | private function evictResultSetCache( |
|
356 | |||
357 | /** |
||
358 | * Evict entity cache region |
||
359 | */ |
||
360 | 2 | private function evictEntityCacheRegion() |
|
374 | |||
375 | /** |
||
376 | * Processes query parameter mappings. |
||
377 | * |
||
378 | * @param array $paramMappings |
||
379 | * |
||
380 | * @return array |
||
381 | * |
||
382 | * @throws Query\QueryException |
||
383 | */ |
||
384 | 447 | private function processParameterMappings($paramMappings) |
|
449 | |||
450 | /** |
||
451 | * Defines a cache driver to be used for caching queries. |
||
452 | * |
||
453 | * @param \Doctrine\Common\Cache\Cache|null $queryCache Cache driver. |
||
454 | * |
||
455 | * @return Query This query instance. |
||
456 | */ |
||
457 | 6 | public function setQueryCacheDriver($queryCache) |
|
463 | |||
464 | /** |
||
465 | * Defines whether the query should make use of a query cache, if available. |
||
466 | * |
||
467 | * @param boolean $bool |
||
468 | * |
||
469 | * @return Query This query instance. |
||
470 | */ |
||
471 | 175 | public function useQueryCache($bool) |
|
477 | |||
478 | /** |
||
479 | * Returns the cache driver used for query caching. |
||
480 | * |
||
481 | * @return \Doctrine\Common\Cache\Cache|null The cache driver used for query caching or NULL, if |
||
482 | * this Query does not use query caching. |
||
483 | */ |
||
484 | 590 | public function getQueryCacheDriver() |
|
492 | |||
493 | /** |
||
494 | * Defines how long the query cache will be active before expire. |
||
495 | * |
||
496 | * @param integer $timeToLive How long the cache entry is valid. |
||
497 | * |
||
498 | * @return Query This query instance. |
||
499 | */ |
||
500 | 1 | public function setQueryCacheLifetime($timeToLive) |
|
510 | |||
511 | /** |
||
512 | * Retrieves the lifetime of resultset cache. |
||
513 | * |
||
514 | * @return int |
||
515 | */ |
||
516 | public function getQueryCacheLifetime() |
||
520 | |||
521 | /** |
||
522 | * Defines if the query cache is active or not. |
||
523 | * |
||
524 | * @param boolean $expire Whether or not to force query cache expiration. |
||
525 | * |
||
526 | * @return Query This query instance. |
||
527 | */ |
||
528 | 7 | public function expireQueryCache($expire = true) |
|
534 | |||
535 | /** |
||
536 | * Retrieves if the query cache is active or not. |
||
537 | * |
||
538 | * @return bool |
||
539 | */ |
||
540 | public function getExpireQueryCache() |
||
544 | |||
545 | /** |
||
546 | * @override |
||
547 | */ |
||
548 | 211 | public function free() |
|
555 | |||
556 | /** |
||
557 | * Sets a DQL query string. |
||
558 | * |
||
559 | * @param string $dqlQuery DQL Query. |
||
560 | * |
||
561 | * @return \Doctrine\ORM\AbstractQuery |
||
562 | */ |
||
563 | 945 | public function setDQL($dqlQuery) |
|
572 | |||
573 | /** |
||
574 | * Returns the DQL query that is represented by this query object. |
||
575 | * |
||
576 | * @return string DQL query. |
||
577 | */ |
||
578 | 897 | public function getDQL() |
|
582 | |||
583 | /** |
||
584 | * Returns the state of this query object |
||
585 | * By default the type is Doctrine_ORM_Query_Abstract::STATE_CLEAN but if it appears any unprocessed DQL |
||
586 | * part, it is switched to Doctrine_ORM_Query_Abstract::STATE_DIRTY. |
||
587 | * |
||
588 | * @see AbstractQuery::STATE_CLEAN |
||
589 | * @see AbstractQuery::STATE_DIRTY |
||
590 | * |
||
591 | * @return integer The query state. |
||
592 | */ |
||
593 | public function getState() |
||
597 | |||
598 | /** |
||
599 | * Method to check if an arbitrary piece of DQL exists |
||
600 | * |
||
601 | * @param string $dql Arbitrary piece of DQL to check for. |
||
602 | * |
||
603 | * @return boolean |
||
604 | */ |
||
605 | public function contains($dql) |
||
609 | |||
610 | /** |
||
611 | * Sets the position of the first result to retrieve (the "offset"). |
||
612 | * |
||
613 | * @param integer $firstResult The first result to return. |
||
614 | * |
||
615 | * @return Query This query object. |
||
616 | */ |
||
617 | 220 | public function setFirstResult($firstResult) |
|
624 | |||
625 | /** |
||
626 | * Gets the position of the first result the query object was set to retrieve (the "offset"). |
||
627 | * Returns NULL if {@link setFirstResult} was not applied to this query. |
||
628 | * |
||
629 | * @return integer The position of the first result. |
||
630 | */ |
||
631 | 647 | public function getFirstResult() |
|
635 | |||
636 | /** |
||
637 | * Sets the maximum number of results to retrieve (the "limit"). |
||
638 | * |
||
639 | * @param integer|null $maxResults |
||
640 | * |
||
641 | * @return Query This query object. |
||
642 | */ |
||
643 | 229 | public function setMaxResults($maxResults) |
|
650 | |||
651 | /** |
||
652 | * Gets the maximum number of results the query object was set to retrieve (the "limit"). |
||
653 | * Returns NULL if {@link setMaxResults} was not applied to this query. |
||
654 | * |
||
655 | * @return integer|null Maximum number of results. |
||
656 | */ |
||
657 | 647 | public function getMaxResults() |
|
661 | |||
662 | /** |
||
663 | * Executes the query and returns an IterableResult that can be used to incrementally |
||
664 | * iterated over the result. |
||
665 | * |
||
666 | * @param ArrayCollection|array|null $parameters The query parameters. |
||
667 | * @param integer $hydrationMode The hydration mode to use. |
||
668 | * |
||
669 | * @return \Doctrine\ORM\Internal\Hydration\IterableResult |
||
670 | */ |
||
671 | 10 | public function iterate($parameters = null, $hydrationMode = self::HYDRATE_OBJECT) |
|
677 | |||
678 | /** |
||
679 | * {@inheritdoc} |
||
680 | */ |
||
681 | 461 | public function setHint($name, $value) |
|
687 | |||
688 | /** |
||
689 | * {@inheritdoc} |
||
690 | */ |
||
691 | 355 | public function setHydrationMode($hydrationMode) |
|
697 | |||
698 | /** |
||
699 | * Set the lock mode for this Query. |
||
700 | * |
||
701 | * @see \Doctrine\DBAL\LockMode |
||
702 | * |
||
703 | * @param int $lockMode |
||
704 | * |
||
705 | * @return Query |
||
706 | * |
||
707 | * @throws TransactionRequiredException |
||
708 | */ |
||
709 | public function setLockMode($lockMode) |
||
721 | |||
722 | /** |
||
723 | * Get the current lock mode for this query. |
||
724 | * |
||
725 | * @return int|null The current lock mode of this query or NULL if no specific lock mode is set. |
||
726 | */ |
||
727 | public function getLockMode() |
||
737 | |||
738 | /** |
||
739 | * Generate a cache id for the query cache - reusing the Result-Cache-Id generator. |
||
740 | * |
||
741 | * @return string |
||
742 | */ |
||
743 | 590 | protected function _getQueryCacheId() |
|
760 | |||
761 | /** |
||
762 | * {@inheritdoc} |
||
763 | */ |
||
764 | 28 | protected function getHash() |
|
768 | |||
769 | /** |
||
770 | * Cleanup Query resource when clone is called. |
||
771 | * |
||
772 | * @return void |
||
773 | */ |
||
774 | 136 | public function __clone() |
|
780 | } |
||
781 |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.