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 integer 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 integer 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 | |||
55 | /** |
||
56 | * Sets the [[indexBy]] property. |
||
57 | * @param string|callable $column the name of the column by which the query results should be indexed by. |
||
58 | * This can also be a callable (e.g. anonymous function) that returns the index value based on the given |
||
59 | * row data. The signature of the callable should be: |
||
60 | * |
||
61 | * ```php |
||
62 | * function ($row) |
||
63 | * { |
||
64 | * // return the index value corresponding to $row |
||
65 | * } |
||
66 | * ``` |
||
67 | * |
||
68 | * @return $this the query object itself |
||
69 | */ |
||
70 | 22 | public function indexBy($column) |
|
75 | |||
76 | /** |
||
77 | * Sets the WHERE part of the query. |
||
78 | * |
||
79 | * See [[QueryInterface::where()]] for detailed documentation. |
||
80 | * |
||
81 | * @param string|array $condition the conditions that should be put in the WHERE part. |
||
82 | * @return $this the query object itself |
||
83 | * @see andWhere() |
||
84 | * @see orWhere() |
||
85 | */ |
||
86 | public function where($condition) |
||
91 | |||
92 | /** |
||
93 | * Adds an additional WHERE condition to the existing one. |
||
94 | * The new condition and the existing one will be joined using the 'AND' operator. |
||
95 | * @param string|array $condition the new WHERE condition. Please refer to [[where()]] |
||
96 | * on how to specify this parameter. |
||
97 | * @return $this the query object itself |
||
98 | * @see where() |
||
99 | * @see orWhere() |
||
100 | */ |
||
101 | public function andWhere($condition) |
||
110 | |||
111 | /** |
||
112 | * Adds an additional WHERE condition to the existing one. |
||
113 | * The new condition and the existing one will be joined using the 'OR' operator. |
||
114 | * @param string|array $condition the new WHERE condition. Please refer to [[where()]] |
||
115 | * on how to specify this parameter. |
||
116 | * @return $this the query object itself |
||
117 | * @see where() |
||
118 | * @see andWhere() |
||
119 | */ |
||
120 | public function orWhere($condition) |
||
129 | |||
130 | /** |
||
131 | * Sets the WHERE part of the query but ignores [[isEmpty()|empty operands]]. |
||
132 | * |
||
133 | * This method is similar to [[where()]]. The main difference is that this method will |
||
134 | * remove [[isEmpty()|empty query operands]]. As a result, this method is best suited |
||
135 | * for building query conditions based on filter values entered by users. |
||
136 | * |
||
137 | * The following code shows the difference between this method and [[where()]]: |
||
138 | * |
||
139 | * ```php |
||
140 | * // WHERE `age`=:age |
||
141 | * $query->filterWhere(['name' => null, 'age' => 20]); |
||
142 | * // WHERE `age`=:age |
||
143 | * $query->where(['age' => 20]); |
||
144 | * // WHERE `name` IS NULL AND `age`=:age |
||
145 | * $query->where(['name' => null, 'age' => 20]); |
||
146 | * ``` |
||
147 | * |
||
148 | * Note that unlike [[where()]], you cannot pass binding parameters to this method. |
||
149 | * |
||
150 | * @param array $condition the conditions that should be put in the WHERE part. |
||
151 | * See [[where()]] on how to specify this parameter. |
||
152 | * @return $this the query object itself |
||
153 | * @see where() |
||
154 | * @see andFilterWhere() |
||
155 | * @see orFilterWhere() |
||
156 | */ |
||
157 | 72 | public function filterWhere(array $condition) |
|
165 | |||
166 | /** |
||
167 | * Adds an additional WHERE condition to the existing one but ignores [[isEmpty()|empty operands]]. |
||
168 | * The new condition and the existing one will be joined using the 'AND' operator. |
||
169 | * |
||
170 | * This method is similar to [[andWhere()]]. The main difference is that this method will |
||
171 | * remove [[isEmpty()|empty query operands]]. As a result, this method is best suited |
||
172 | * for building query conditions based on filter values entered by users. |
||
173 | * |
||
174 | * @param array $condition the new WHERE condition. Please refer to [[where()]] |
||
175 | * on how to specify this parameter. |
||
176 | * @return $this the query object itself |
||
177 | * @see filterWhere() |
||
178 | * @see orFilterWhere() |
||
179 | */ |
||
180 | 3 | public function andFilterWhere(array $condition) |
|
188 | |||
189 | /** |
||
190 | * Adds an additional WHERE condition to the existing one but ignores [[isEmpty()|empty operands]]. |
||
191 | * The new condition and the existing one will be joined using the 'OR' operator. |
||
192 | * |
||
193 | * This method is similar to [[orWhere()]]. The main difference is that this method will |
||
194 | * remove [[isEmpty()|empty query operands]]. As a result, this method is best suited |
||
195 | * for building query conditions based on filter values entered by users. |
||
196 | * |
||
197 | * @param array $condition the new WHERE condition. Please refer to [[where()]] |
||
198 | * on how to specify this parameter. |
||
199 | * @return $this the query object itself |
||
200 | * @see filterWhere() |
||
201 | * @see andFilterWhere() |
||
202 | */ |
||
203 | 3 | public function orFilterWhere(array $condition) |
|
211 | |||
212 | /** |
||
213 | * Removes [[isEmpty()|empty operands]] from the given query condition. |
||
214 | * |
||
215 | * @param array $condition the original condition |
||
216 | * @return array the condition with [[isEmpty()|empty operands]] removed. |
||
217 | * @throws NotSupportedException if the condition operator is not supported |
||
218 | */ |
||
219 | 72 | protected function filterCondition($condition) |
|
274 | |||
275 | /** |
||
276 | * Returns a value indicating whether the give value is "empty". |
||
277 | * |
||
278 | * The value is considered "empty", if one of the following conditions is satisfied: |
||
279 | * |
||
280 | * - it is `null`, |
||
281 | * - an empty string (`''`), |
||
282 | * - a string containing only whitespace characters, |
||
283 | * - or an empty array. |
||
284 | * |
||
285 | * @param mixed $value |
||
286 | * @return boolean if the value is empty |
||
287 | */ |
||
288 | 72 | protected function isEmpty($value) |
|
292 | |||
293 | /** |
||
294 | * Sets the ORDER BY part of the query. |
||
295 | * @param string|array|Expression $columns the columns (and the directions) to be ordered by. |
||
296 | * Columns can be specified in either a string (e.g. `"id ASC, name DESC"`) or an array |
||
297 | * (e.g. `['id' => SORT_ASC, 'name' => SORT_DESC]`). |
||
298 | * |
||
299 | * The method will automatically quote the column names unless a column contains some parenthesis |
||
300 | * (which means the column contains a DB expression). |
||
301 | * |
||
302 | * Note that if your order-by is an expression containing commas, you should always use an array |
||
303 | * to represent the order-by information. Otherwise, the method will not be able to correctly determine |
||
304 | * the order-by columns. |
||
305 | * |
||
306 | * Since version 2.0.7, an [[Expression]] object can be passed to specify the ORDER BY part explicitly in plain SQL. |
||
307 | * @return $this the query object itself |
||
308 | * @see addOrderBy() |
||
309 | */ |
||
310 | 118 | public function orderBy($columns) |
|
315 | |||
316 | /** |
||
317 | * Adds additional ORDER BY columns to the query. |
||
318 | * @param string|array|Expression $columns the columns (and the directions) to be ordered by. |
||
319 | * Columns can be specified in either a string (e.g. "id ASC, name DESC") or an array |
||
320 | * (e.g. `['id' => SORT_ASC, 'name' => SORT_DESC]`). |
||
321 | * |
||
322 | * The method will automatically quote the column names unless a column contains some parenthesis |
||
323 | * (which means the column contains a DB expression). |
||
324 | * |
||
325 | * Note that if your order-by is an expression containing commas, you should always use an array |
||
326 | * to represent the order-by information. Otherwise, the method will not be able to correctly determine |
||
327 | * the order-by columns. |
||
328 | * |
||
329 | * Since version 2.0.7, an [[Expression]] object can be passed to specify the ORDER BY part explicitly in plain SQL. |
||
330 | * @return $this the query object itself |
||
331 | * @see orderBy() |
||
332 | */ |
||
333 | 33 | public function addOrderBy($columns) |
|
343 | |||
344 | /** |
||
345 | * Normalizes format of ORDER BY data |
||
346 | * |
||
347 | * @param array|string|Expression $columns the columns value to normalize. See [[orderBy]] and [[addOrderBy]]. |
||
348 | * @return array |
||
349 | */ |
||
350 | 118 | protected function normalizeOrderBy($columns) |
|
369 | |||
370 | /** |
||
371 | * Sets the LIMIT part of the query. |
||
372 | * @param integer $limit the limit. Use null or negative value to disable limit. |
||
373 | * @return $this the query object itself |
||
374 | */ |
||
375 | 50 | public function limit($limit) |
|
380 | |||
381 | /** |
||
382 | * Sets the OFFSET part of the query. |
||
383 | * @param integer $offset the offset. Use null or negative value to disable offset. |
||
384 | * @return $this the query object itself |
||
385 | */ |
||
386 | 33 | public function offset($offset) |
|
391 | } |
||
392 |