Complex classes like QueryTrait 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 QueryTrait, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
21 | trait QueryTrait |
||
22 | { |
||
23 | /** |
||
24 | * @var string|array query condition. This refers to the WHERE clause in a SQL statement. |
||
25 | * For example, `['age' => 31, 'team' => 1]`. |
||
26 | * @see where() for valid syntax on specifying this value. |
||
27 | */ |
||
28 | public $where; |
||
29 | /** |
||
30 | * @var int maximum number of records to be returned. If not set or less than 0, it means no limit. |
||
31 | */ |
||
32 | public $limit; |
||
33 | /** |
||
34 | * @var int zero-based offset from where the records are to be returned. If not set or |
||
35 | * less than 0, it means starting from the beginning. |
||
36 | */ |
||
37 | public $offset; |
||
38 | /** |
||
39 | * @var array how to sort the query results. This is used to construct the ORDER BY clause in a SQL statement. |
||
40 | * The array keys are the columns to be sorted by, and the array values are the corresponding sort directions which |
||
41 | * can be either [SORT_ASC](http://php.net/manual/en/array.constants.php#constant.sort-asc) |
||
42 | * or [SORT_DESC](http://php.net/manual/en/array.constants.php#constant.sort-desc). |
||
43 | * The array may also contain [[Expression]] objects. If that is the case, the expressions |
||
44 | * will be converted into strings without any change. |
||
45 | */ |
||
46 | public $orderBy; |
||
47 | /** |
||
48 | * @var string|callable $column the name of the column by which the query results should be indexed by. |
||
49 | * This can also be a callable (e.g. anonymous function) that returns the index value based on the given |
||
50 | * row data. For more details, see [[indexBy()]]. This property is only used by [[QueryInterface::all()|all()]]. |
||
51 | */ |
||
52 | public $indexBy; |
||
53 | /** |
||
54 | * @var boolean whether to emulate the actual query execution, returning empty or false results. |
||
55 | * @see emulateExecution() |
||
56 | * @since 2.0.11 |
||
57 | */ |
||
58 | public $emulateExecution = false; |
||
59 | |||
60 | |||
61 | /** |
||
62 | * Sets the [[indexBy]] property. |
||
63 | * @param string|callable $column the name of the column by which the query results should be indexed by. |
||
64 | * This can also be a callable (e.g. anonymous function) that returns the index value based on the given |
||
65 | * row data. The signature of the callable should be: |
||
66 | * |
||
67 | * ```php |
||
68 | * function ($row) |
||
69 | * { |
||
70 | * // return the index value corresponding to $row |
||
71 | * } |
||
72 | * ``` |
||
73 | * |
||
74 | * @return $this the query object itself |
||
75 | */ |
||
76 | 36 | public function indexBy($column) |
|
81 | |||
82 | /** |
||
83 | * Sets the WHERE part of the query. |
||
84 | * |
||
85 | * See [[QueryInterface::where()]] for detailed documentation. |
||
86 | * |
||
87 | * @param string|array $condition the conditions that should be put in the WHERE part. |
||
88 | * @return $this the query object itself |
||
89 | * @see andWhere() |
||
90 | * @see orWhere() |
||
91 | */ |
||
92 | public function where($condition) |
||
97 | |||
98 | /** |
||
99 | * Adds an additional WHERE condition to the existing one. |
||
100 | * The new condition and the existing one will be joined using the 'AND' operator. |
||
101 | * @param string|array $condition the new WHERE condition. Please refer to [[where()]] |
||
102 | * on how to specify this parameter. |
||
103 | * @return $this the query object itself |
||
104 | * @see where() |
||
105 | * @see orWhere() |
||
106 | */ |
||
107 | public function andWhere($condition) |
||
116 | |||
117 | /** |
||
118 | * Adds an additional WHERE condition to the existing one. |
||
119 | * The new condition and the existing one will be joined using the 'OR' operator. |
||
120 | * @param string|array $condition the new WHERE condition. Please refer to [[where()]] |
||
121 | * on how to specify this parameter. |
||
122 | * @return $this the query object itself |
||
123 | * @see where() |
||
124 | * @see andWhere() |
||
125 | */ |
||
126 | public function orWhere($condition) |
||
135 | |||
136 | /** |
||
137 | * Sets the WHERE part of the query but ignores [[isEmpty()|empty operands]]. |
||
138 | * |
||
139 | * This method is similar to [[where()]]. The main difference is that this method will |
||
140 | * remove [[isEmpty()|empty query operands]]. As a result, this method is best suited |
||
141 | * for building query conditions based on filter values entered by users. |
||
142 | * |
||
143 | * The following code shows the difference between this method and [[where()]]: |
||
144 | * |
||
145 | * ```php |
||
146 | * // WHERE `age`=:age |
||
147 | * $query->filterWhere(['name' => null, 'age' => 20]); |
||
148 | * // WHERE `age`=:age |
||
149 | * $query->where(['age' => 20]); |
||
150 | * // WHERE `name` IS NULL AND `age`=:age |
||
151 | * $query->where(['name' => null, 'age' => 20]); |
||
152 | * ``` |
||
153 | * |
||
154 | * Note that unlike [[where()]], you cannot pass binding parameters to this method. |
||
155 | * |
||
156 | * @param array $condition the conditions that should be put in the WHERE part. |
||
157 | * See [[where()]] on how to specify this parameter. |
||
158 | * @return $this the query object itself |
||
159 | * @see where() |
||
160 | * @see andFilterWhere() |
||
161 | * @see orFilterWhere() |
||
162 | */ |
||
163 | 72 | public function filterWhere(array $condition) |
|
171 | |||
172 | /** |
||
173 | * Adds an additional WHERE condition to the existing one but ignores [[isEmpty()|empty operands]]. |
||
174 | * The new condition and the existing one will be joined using the 'AND' operator. |
||
175 | * |
||
176 | * This method is similar to [[andWhere()]]. The main difference is that this method will |
||
177 | * remove [[isEmpty()|empty query operands]]. As a result, this method is best suited |
||
178 | * for building query conditions based on filter values entered by users. |
||
179 | * |
||
180 | * @param array $condition the new WHERE condition. Please refer to [[where()]] |
||
181 | * on how to specify this parameter. |
||
182 | * @return $this the query object itself |
||
183 | * @see filterWhere() |
||
184 | * @see orFilterWhere() |
||
185 | */ |
||
186 | 6 | public function andFilterWhere(array $condition) |
|
194 | |||
195 | /** |
||
196 | * Adds an additional WHERE condition to the existing one but ignores [[isEmpty()|empty operands]]. |
||
197 | * The new condition and the existing one will be joined using the 'OR' operator. |
||
198 | * |
||
199 | * This method is similar to [[orWhere()]]. The main difference is that this method will |
||
200 | * remove [[isEmpty()|empty query operands]]. As a result, this method is best suited |
||
201 | * for building query conditions based on filter values entered by users. |
||
202 | * |
||
203 | * @param array $condition the new WHERE condition. Please refer to [[where()]] |
||
204 | * on how to specify this parameter. |
||
205 | * @return $this the query object itself |
||
206 | * @see filterWhere() |
||
207 | * @see andFilterWhere() |
||
208 | */ |
||
209 | 3 | public function orFilterWhere(array $condition) |
|
217 | |||
218 | /** |
||
219 | * Removes [[isEmpty()|empty operands]] from the given query condition. |
||
220 | * |
||
221 | * @param array $condition the original condition |
||
222 | * @return array the condition with [[isEmpty()|empty operands]] removed. |
||
223 | * @throws NotSupportedException if the condition operator is not supported |
||
224 | */ |
||
225 | 75 | protected function filterCondition($condition) |
|
280 | |||
281 | /** |
||
282 | * Returns a value indicating whether the give value is "empty". |
||
283 | * |
||
284 | * The value is considered "empty", if one of the following conditions is satisfied: |
||
285 | * |
||
286 | * - it is `null`, |
||
287 | * - an empty string (`''`), |
||
288 | * - a string containing only whitespace characters, |
||
289 | * - or an empty array. |
||
290 | * |
||
291 | * @param mixed $value |
||
292 | * @return bool if the value is empty |
||
293 | */ |
||
294 | 75 | protected function isEmpty($value) |
|
298 | |||
299 | /** |
||
300 | * Sets the ORDER BY part of the query. |
||
301 | * @param string|array|Expression $columns the columns (and the directions) to be ordered by. |
||
302 | * Columns can be specified in either a string (e.g. `"id ASC, name DESC"`) or an array |
||
303 | * (e.g. `['id' => SORT_ASC, 'name' => SORT_DESC]`). |
||
304 | * |
||
305 | * The method will automatically quote the column names unless a column contains some parenthesis |
||
306 | * (which means the column contains a DB expression). |
||
307 | * |
||
308 | * Note that if your order-by is an expression containing commas, you should always use an array |
||
309 | * to represent the order-by information. Otherwise, the method will not be able to correctly determine |
||
310 | * the order-by columns. |
||
311 | * |
||
312 | * Since version 2.0.7, an [[Expression]] object can be passed to specify the ORDER BY part explicitly in plain SQL. |
||
313 | * @return $this the query object itself |
||
314 | * @see addOrderBy() |
||
315 | */ |
||
316 | 142 | public function orderBy($columns) |
|
321 | |||
322 | /** |
||
323 | * Adds additional ORDER BY columns to the query. |
||
324 | * @param string|array|Expression $columns the columns (and the directions) to be ordered by. |
||
325 | * Columns can be specified in either a string (e.g. "id ASC, name DESC") or an array |
||
326 | * (e.g. `['id' => SORT_ASC, 'name' => SORT_DESC]`). |
||
327 | * |
||
328 | * The method will automatically quote the column names unless a column contains some parenthesis |
||
329 | * (which means the column contains a DB expression). |
||
330 | * |
||
331 | * Note that if your order-by is an expression containing commas, you should always use an array |
||
332 | * to represent the order-by information. Otherwise, the method will not be able to correctly determine |
||
333 | * the order-by columns. |
||
334 | * |
||
335 | * Since version 2.0.7, an [[Expression]] object can be passed to specify the ORDER BY part explicitly in plain SQL. |
||
336 | * @return $this the query object itself |
||
337 | * @see orderBy() |
||
338 | */ |
||
339 | 36 | public function addOrderBy($columns) |
|
349 | |||
350 | /** |
||
351 | * Normalizes format of ORDER BY data |
||
352 | * |
||
353 | * @param array|string|Expression $columns the columns value to normalize. See [[orderBy]] and [[addOrderBy]]. |
||
354 | * @return array |
||
355 | */ |
||
356 | 142 | protected function normalizeOrderBy($columns) |
|
375 | |||
376 | /** |
||
377 | * Sets the LIMIT part of the query. |
||
378 | * @param int $limit the limit. Use null or negative value to disable limit. |
||
379 | * @return $this the query object itself |
||
380 | */ |
||
381 | 56 | public function limit($limit) |
|
386 | |||
387 | /** |
||
388 | * Sets the OFFSET part of the query. |
||
389 | * @param int $offset the offset. Use null or negative value to disable offset. |
||
390 | * @return $this the query object itself |
||
391 | */ |
||
392 | 33 | public function offset($offset) |
|
397 | |||
398 | /** |
||
399 | * Sets whether to emulate query execution, preventing any interaction with data storage. |
||
400 | * After this mode is enabled, methods, returning query results like [[one()]], [[all()]], [[exists()]] |
||
401 | * and so on, will return empty or false values. |
||
402 | * You should use this method in case your program logic indicates query should not return any results, like |
||
403 | * in case you set false where condition like `0=1`. |
||
404 | * @param boolean $value whether to prevent query execution. |
||
405 | * @return $this the query object itself. |
||
406 | * @since 2.0.11 |
||
407 | */ |
||
408 | 21 | public function emulateExecution($value = true) |
|
413 | } |
||
414 |