Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
1 | <?php |
||
36 | abstract class AbstractSelect extends AbstractWhere implements |
||
37 | \IteratorAggregate, |
||
38 | PaginableInterface, |
||
39 | PaginatorAwareInterface, |
||
40 | \JsonSerializable |
||
41 | { |
||
42 | /** |
||
43 | * Abstract select query must fully support joins and be paginable. |
||
44 | */ |
||
45 | use JoinsTrait, PaginatorTrait; |
||
46 | |||
47 | /** |
||
48 | * Sort directions. |
||
49 | */ |
||
50 | const SORT_ASC = 'ASC'; |
||
51 | const SORT_DESC = 'DESC'; |
||
52 | |||
53 | /** |
||
54 | * Query must return only unique rows. |
||
55 | * |
||
56 | * @var bool|string |
||
57 | */ |
||
58 | protected $distinct = false; |
||
59 | |||
60 | /** |
||
61 | * Columns or expressions to be fetched from database, can include aliases (AS). |
||
62 | * |
||
63 | * @var array |
||
64 | */ |
||
65 | protected $columns = ['*']; |
||
66 | |||
67 | /** |
||
68 | * Set of generated having tokens, format must be supported by QueryCompilers. |
||
69 | * |
||
70 | * @see AbstractWhere |
||
71 | * @var array |
||
72 | */ |
||
73 | protected $havingTokens = []; |
||
74 | |||
75 | /** |
||
76 | * Parameters collected while generating HAVING tokens, must be in a same order as parameters |
||
77 | * in resulted query. |
||
78 | * |
||
79 | * @see AbstractWhere |
||
80 | * @var array |
||
81 | */ |
||
82 | protected $havingParameters = []; |
||
83 | |||
84 | /** |
||
85 | * Columns/expression associated with their sort direction (ASK|DESC). |
||
86 | * |
||
87 | * @var array |
||
88 | */ |
||
89 | protected $ordering = []; |
||
90 | |||
91 | /** |
||
92 | * Columns/expressions to group by. |
||
93 | * |
||
94 | * @var array |
||
95 | */ |
||
96 | protected $grouping = []; |
||
97 | |||
98 | /** |
||
99 | * Associated cache store. |
||
100 | * |
||
101 | * @var StoreInterface |
||
102 | */ |
||
103 | protected $cacheStore = null; |
||
104 | |||
105 | /** |
||
106 | * Cache lifetime in seconds. |
||
107 | * |
||
108 | * @var int |
||
109 | */ |
||
110 | protected $cacheLifetime = 0; |
||
111 | |||
112 | /** |
||
113 | * User specified cache key (optional). |
||
114 | * |
||
115 | * @var string |
||
116 | */ |
||
117 | protected $cacheKey = ''; |
||
118 | |||
119 | /** |
||
120 | * {@inheritdoc} |
||
121 | */ |
||
122 | View Code Duplication | public function getParameters(QueryCompiler $compiler = null) |
|
138 | |||
139 | /** |
||
140 | * Mark query to return only distinct results. |
||
141 | * |
||
142 | * @param bool|string $distinct You are only allowed to use string value for Postgres databases. |
||
143 | * @return $this |
||
144 | */ |
||
145 | public function distinct($distinct = true) |
||
151 | |||
152 | /** |
||
153 | * Simple HAVING condition with various set of arguments. |
||
154 | * |
||
155 | * @see AbstractWhere |
||
156 | * @param string|mixed $identifier Column or expression. |
||
157 | * @param mixed $variousA Operator or value. |
||
158 | * @param mixed $variousB Value, if operator specified. |
||
159 | * @param mixed $variousC Required only in between statements. |
||
160 | * @return $this |
||
161 | * @throws BuilderException |
||
162 | */ |
||
163 | public function having($identifier, $variousA = null, $variousB = null, $variousC = null) |
||
169 | |||
170 | /** |
||
171 | * Simple AND HAVING condition with various set of arguments. |
||
172 | * |
||
173 | * @see AbstractWhere |
||
174 | * @param string|mixed $identifier Column or expression. |
||
175 | * @param mixed $variousA Operator or value. |
||
176 | * @param mixed $variousB Value, if operator specified. |
||
177 | * @param mixed $variousC Required only in between statements. |
||
178 | * @return $this |
||
179 | * @throws BuilderException |
||
180 | */ |
||
181 | public function andHaving($identifier, $variousA = null, $variousB = null, $variousC = null) |
||
187 | |||
188 | /** |
||
189 | * Simple OR HAVING condition with various set of arguments. |
||
190 | * |
||
191 | * @see AbstractWhere |
||
192 | * @param string|mixed $identifier Column or expression. |
||
193 | * @param mixed $variousA Operator or value. |
||
194 | * @param mixed $variousB Value, if operator specified. |
||
195 | * @param mixed $variousC Required only in between statements. |
||
196 | * @return $this |
||
197 | * @throws BuilderException |
||
198 | */ |
||
199 | public function orHaving($identifier, $variousA = [], $variousB = null, $variousC = null) |
||
205 | |||
206 | /** |
||
207 | * Sort result by column/expression. You can apply multiple sortings to query via calling method |
||
208 | * few times or by specifying values using array of sort parameters: |
||
209 | * |
||
210 | * $select->orderBy([ |
||
211 | * 'id' => SelectQuery::SORT_DESC, |
||
212 | * 'name' => SelectQuery::SORT_ASC |
||
213 | * ]); |
||
214 | * |
||
215 | * @param string|array $expression |
||
216 | * @param string $direction Sorting direction, ASC|DESC. |
||
217 | * @return $this |
||
218 | */ |
||
219 | public function orderBy($expression, $direction = self::SORT_ASC) |
||
233 | |||
234 | /** |
||
235 | * Column or expression to group query by. |
||
236 | * |
||
237 | * @param string $expression |
||
238 | * @return $this |
||
239 | */ |
||
240 | public function groupBy($expression) |
||
246 | |||
247 | /** |
||
248 | * Mark selection as cached one, result will be passed thought database->cached() method and |
||
249 | * will be stored in cache storage for specified amount of seconds. |
||
250 | * |
||
251 | * @see Database::cached() |
||
252 | * @param int $lifetime Cache lifetime in seconds. |
||
253 | * @param string $key Optional, Database will generate key based on query. |
||
254 | * @param StoreInterface $store Optional, Database will resolve cache store using container. |
||
255 | * @return $this |
||
256 | */ |
||
257 | public function cache($lifetime, $key = '', StoreInterface $store = null) |
||
265 | |||
266 | /** |
||
267 | * {@inheritdoc} |
||
268 | * |
||
269 | * @param bool $paginate Apply pagination to result, can be disabled in honor of count method. |
||
270 | * @return QueryResult|CachedResult |
||
271 | */ |
||
272 | public function run($paginate = true) |
||
303 | |||
304 | /** |
||
305 | * Iterate thought result using smaller data chinks with defined size and walk function. |
||
306 | * |
||
307 | * Example: |
||
308 | * $select->chunked(100, function(QueryResult $result, $offset, $count) { |
||
309 | * dump($result); |
||
310 | * }); |
||
311 | * |
||
312 | * You must return FALSE from walk function to stop chunking. |
||
313 | * |
||
314 | * @param int $limit |
||
315 | * @param callable $callback |
||
316 | */ |
||
317 | public function chunked($limit, callable $callback) |
||
339 | |||
340 | /** |
||
341 | * {@inheritdoc} |
||
342 | * |
||
343 | * Count number of rows in query. Limit, offset, order by, group by values will be ignored. Do |
||
344 | * not count united queries, or queries in complex joins. |
||
345 | * |
||
346 | * @param string $column Column to count by (every column by default). |
||
347 | * @return int |
||
348 | */ |
||
349 | public function count($column = '*') |
||
363 | |||
364 | /** |
||
365 | * {@inheritdoc} |
||
366 | * |
||
367 | * Shortcut to execute one of aggregation methods (AVG, MAX, MIN, SUM) using method name as |
||
368 | * reference. |
||
369 | * |
||
370 | * Example: |
||
371 | * echo $select->sum('user.balance'); |
||
372 | * |
||
373 | * @param string $method |
||
374 | * @param string $arguments |
||
375 | * @return int |
||
376 | * @throws BuilderException |
||
377 | * @throws QueryException |
||
378 | */ |
||
379 | public function __call($method, $arguments) |
||
396 | |||
397 | /** |
||
398 | * {@inheritdoc} |
||
399 | * |
||
400 | * @return QueryResult |
||
401 | */ |
||
402 | public function getIterator() |
||
406 | |||
407 | /** |
||
408 | * {@inheritdoc} |
||
409 | */ |
||
410 | public function jsonSerialize() |
||
414 | |||
415 | /** |
||
416 | * Applied to every potential parameter while having tokens generation. |
||
417 | * |
||
418 | * @return \Closure |
||
419 | */ |
||
420 | View Code Duplication | private function havingWrapper() |
|
445 | } |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.