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:
Complex classes like Table 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 Table, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
55 | class Table |
||
56 | { |
||
57 | /** |
||
58 | * @var \Phinx\Db\Table\Table |
||
59 | */ |
||
60 | protected $table; |
||
61 | |||
62 | /** |
||
63 | * @var \Phinx\Db\Adapter\AdapterInterface |
||
64 | */ |
||
65 | protected $adapter; |
||
66 | |||
67 | |||
68 | /** |
||
69 | * @var \Phinx\Db\Plan\Intent |
||
70 | */ |
||
71 | protected $actions; |
||
72 | |||
73 | /** |
||
74 | * @var array |
||
75 | */ |
||
76 | protected $data = []; |
||
77 | |||
78 | /** |
||
79 | * Class Constuctor. |
||
80 | * |
||
81 | * @param string $name Table Name |
||
82 | * @param array $options Options |
||
83 | * @param \Phinx\Db\Adapter\AdapterInterface $adapter Database Adapter |
||
84 | 239 | */ |
|
85 | public function __construct($name, $options = [], AdapterInterface $adapter = null) |
||
94 | |||
95 | /** |
||
96 | * Gets the table name. |
||
97 | * |
||
98 | * @return string|null |
||
99 | */ |
||
100 | 239 | public function getName() |
|
104 | |||
105 | /** |
||
106 | * Gets the table options. |
||
107 | * |
||
108 | * @return array |
||
109 | */ |
||
110 | public function getOptions() |
||
114 | |||
115 | /** |
||
116 | * Gets the table name and options as an object |
||
117 | * |
||
118 | * @return \Phinx\Db\Table\Table |
||
119 | */ |
||
120 | public function getTable() |
||
124 | 239 | ||
125 | 239 | /** |
|
126 | * Sets the database adapter. |
||
127 | * |
||
128 | * @param \Phinx\Db\Adapter\AdapterInterface $adapter Database Adapter |
||
129 | * @return \Phinx\Db\Table |
||
130 | */ |
||
131 | public function setAdapter(AdapterInterface $adapter) |
||
137 | |||
138 | /** |
||
139 | * Gets the database adapter. |
||
140 | * |
||
141 | * @return \Phinx\Db\Adapter\AdapterInterface|null |
||
142 | */ |
||
143 | public function getAdapter() |
||
151 | |||
152 | /** |
||
153 | * Does the table exist? |
||
154 | * |
||
155 | 225 | * @return bool |
|
156 | */ |
||
157 | 225 | public function exists() |
|
161 | |||
162 | /** |
||
163 | * Drops the database table. |
||
164 | * |
||
165 | 195 | * @return \Phinx\Db\Table |
|
166 | */ |
||
167 | 195 | public function drop() |
|
173 | |||
174 | /** |
||
175 | 1 | * Renames the database table. |
|
176 | * |
||
177 | 1 | * @param string $newTableName New Table Name |
|
178 | 1 | * @return \Phinx\Db\Table |
|
179 | */ |
||
180 | public function rename($newTableName) |
||
186 | 3 | ||
187 | /** |
||
188 | 3 | * Gets an array of the table columns. |
|
189 | 3 | * |
|
190 | 3 | * @return \Phinx\Db\Table\Column[] |
|
191 | */ |
||
192 | public function getColumns() |
||
196 | |||
197 | /** |
||
198 | * Sets an array of data to be inserted. |
||
199 | * |
||
200 | * @param array $data Data |
||
201 | * @return \Phinx\Db\Table |
||
202 | */ |
||
203 | public function setData($data) |
||
209 | |||
210 | /** |
||
211 | 10 | * Gets the data waiting to be inserted. |
|
212 | * |
||
213 | 10 | * @return array |
|
214 | */ |
||
215 | public function getData() |
||
219 | |||
220 | /** |
||
221 | * Resets all of the pending table changes. |
||
222 | 196 | * |
|
223 | * @return void |
||
224 | 196 | */ |
|
225 | 196 | public function reset() |
|
230 | |||
231 | /** |
||
232 | * Add a table column. |
||
233 | 204 | * |
|
234 | * Type can be: string, text, integer, float, decimal, datetime, timestamp, |
||
235 | 204 | * time, date, binary, boolean. |
|
236 | * |
||
237 | * Valid options can be: limit, default, null, precision or scale. |
||
238 | * |
||
239 | * @param string|\Phinx\Db\Table\Column $columnName Column Name |
||
240 | * @param string|\Phinx\Util\Literal $type Column Type |
||
241 | * @param array $options Column Options |
||
242 | * @throws \RuntimeException |
||
243 | * @throws \InvalidArgumentException |
||
244 | 196 | * @return \Phinx\Db\Table |
|
245 | */ |
||
246 | 196 | public function addColumn($columnName, $type = null, $options = []) |
|
247 | 196 | { |
|
248 | View Code Duplication | if ($columnName instanceof Column) { |
|
|
|||
249 | $action = new AddColumn($this->table, $columnName); |
||
250 | } else { |
||
251 | $action = AddColumn::build($this->table, $columnName, $type, $options); |
||
252 | } |
||
253 | |||
254 | // Delegate to Adapters to check column type |
||
255 | 191 | if (!$this->getAdapter()->isValidColumnType($action->getColumn())) { |
|
256 | throw new \InvalidArgumentException(sprintf( |
||
257 | 191 | 'An invalid column type "%s" was specified for column "%s".', |
|
258 | $type, |
||
259 | $action->getColumn()->getName() |
||
260 | )); |
||
261 | } |
||
262 | |||
263 | $this->actions->addAction($action); |
||
264 | |||
265 | return $this; |
||
266 | 196 | } |
|
267 | |||
268 | 196 | /** |
|
269 | 196 | * Remove a table column. |
|
270 | * |
||
271 | * @param string $columnName Column Name |
||
272 | * @return \Phinx\Db\Table |
||
273 | */ |
||
274 | public function removeColumn($columnName) |
||
281 | |||
282 | /** |
||
283 | * Rename a table column. |
||
284 | * |
||
285 | * @param string $oldName Old Column Name |
||
286 | * @param string $newName New Column Name |
||
287 | * @return \Phinx\Db\Table |
||
288 | 196 | */ |
|
289 | public function renameColumn($oldName, $newName) |
||
296 | |||
297 | /** |
||
298 | * Change a table column type. |
||
299 | 197 | * |
|
300 | * @param string $columnName Column Name |
||
301 | 197 | * @param string|\Phinx\Db\Table\Column|\Phinx\Util\Literal $newColumnType New Column Type |
|
302 | * @param array $options Options |
||
303 | * @return \Phinx\Db\Table |
||
304 | */ |
||
305 | public function changeColumn($columnName, $newColumnType, array $options = []) |
||
316 | |||
317 | /** |
||
318 | * Checks to see if a column exists. |
||
319 | * |
||
320 | * @param string $columnName Column Name |
||
321 | * @return bool |
||
322 | */ |
||
323 | public function hasColumn($columnName) |
||
327 | |||
328 | /** |
||
329 | * Add an index to a database table. |
||
330 | * |
||
331 | * In $options you can specific unique = true/false or name (index name). |
||
332 | 210 | * |
|
333 | * @param string|array|\Phinx\Db\Table\Index $columns Table Column(s) |
||
334 | * @param array $options Index Options |
||
335 | 210 | * @return \Phinx\Db\Table |
|
336 | 1 | */ |
|
337 | public function addIndex($columns, array $options = []) |
||
344 | 207 | ||
345 | 207 | /** |
|
346 | 2 | * Removes the given index from a table. |
|
347 | * |
||
348 | * @param array $columns Columns |
||
349 | * @return \Phinx\Db\Table |
||
350 | 209 | */ |
|
351 | 1 | public function removeIndex(array $columns) |
|
358 | 208 | ||
359 | 208 | /** |
|
360 | * Removes the given index identified by its name from a table. |
||
361 | * |
||
362 | * @param string $name Index name |
||
363 | * @return \Phinx\Db\Table |
||
364 | */ |
||
365 | public function removeIndexByName($name) |
||
372 | |||
373 | /** |
||
374 | * Checks to see if an index exists. |
||
375 | * |
||
376 | * @param string|array $columns Columns |
||
377 | * @return bool |
||
378 | */ |
||
379 | public function hasIndex($columns) |
||
383 | 4 | ||
384 | 4 | /** |
|
385 | * Checks to see if an index specified by name exists. |
||
386 | * |
||
387 | * @param string $indexName |
||
388 | * @return bool |
||
389 | */ |
||
390 | public function hasIndexByName($indexName) |
||
394 | |||
395 | 17 | /** |
|
396 | * Add a foreign key to a database table. |
||
397 | * |
||
398 | 17 | * In $options you can specify on_delete|on_delete = cascade|no_action .., |
|
399 | 4 | * on_update, constraint = constraint name. |
|
400 | 4 | * |
|
401 | 4 | * @param string|array $columns Columns |
|
402 | 4 | * @param string|\Phinx\Db\Table $referencedTable Referenced Table |
|
403 | 13 | * @param string|array $referencedColumns Referenced Columns |
|
404 | * @param array $options Options |
||
405 | * @return \Phinx\Db\Table |
||
406 | */ |
||
407 | 17 | View Code Duplication | public function addForeignKey($columns, $referencedTable, $referencedColumns = ['id'], $options = []) |
414 | |||
415 | /** |
||
416 | * Add a foreign key to a database table with a given name. |
||
417 | * |
||
418 | * In $options you can specify on_delete|on_delete = cascade|no_action .., |
||
419 | * on_update, constraint = constraint name. |
||
420 | * |
||
421 | 89 | * @param string $name The constaint name |
|
422 | * @param string|array $columns Columns |
||
423 | 89 | * @param string|\Phinx\Db\Table $referencedTable Referenced Table |
|
424 | * @param string|array $referencedColumns Referenced Columns |
||
425 | * @param array $options Options |
||
426 | * @return \Phinx\Db\Table |
||
427 | */ |
||
428 | View Code Duplication | public function addForeignKeyWithName($name, $columns, $referencedTable, $referencedColumns = ['id'], $options = []) |
|
442 | 22 | ||
443 | 28 | /** |
|
444 | 28 | * Removes the given foreign key from the table. |
|
445 | 28 | * |
|
446 | 1 | * @param string|array $columns Column(s) |
|
447 | * @param null|string $constraint Constraint names |
||
448 | * @return \Phinx\Db\Table |
||
449 | 29 | */ |
|
450 | 29 | View Code Duplication | public function dropForeignKey($columns, $constraint = null) |
457 | |||
458 | /** |
||
459 | 1 | * Checks to see if a foreign key exists. |
|
460 | * |
||
461 | 1 | * @param string|array $columns Column(s) |
|
462 | 1 | * @param null|string $constraint Constraint names |
|
463 | * @return bool |
||
464 | */ |
||
465 | public function hasForeignKey($columns, $constraint = null) |
||
469 | |||
470 | /** |
||
471 | 1 | * Add timestamp columns created_at and updated_at to the table. |
|
472 | * |
||
473 | 1 | * @param string|null $createdAt Alternate name for the created_at column |
|
474 | 1 | * @param string|null $updatedAt Alternate name for the updated_at column |
|
475 | * @param bool $withTimezone Whether to set the timezone option on the added columns |
||
476 | * |
||
477 | * @return \Phinx\Db\Table |
||
478 | */ |
||
479 | public function addTimestamps($createdAt = 'created_at', $updatedAt = 'updated_at', $withTimezone = false) |
||
497 | |||
498 | /** |
||
499 | * Alias that always sets $withTimezone to true |
||
500 | * @see addTimestamps |
||
501 | 8 | * |
|
502 | * @param string|null $createdAt Alternate name for the created_at column |
||
503 | 8 | * @param string|null $updatedAt Alternate name for the updated_at column |
|
504 | 4 | * |
|
505 | 4 | * @return \Phinx\Db\Table |
|
506 | 8 | */ |
|
507 | 8 | public function addTimestampsWithTimezone($createdAt = null, $updatedAt = null) |
|
513 | 8 | ||
514 | 8 | /** |
|
515 | 8 | * Insert data into the table. |
|
516 | * |
||
517 | 8 | * @param array $data array of data in the form: |
|
518 | * array( |
||
519 | * array("col1" => "value1", "col2" => "anotherValue1"), |
||
520 | * array("col2" => "value2", "col2" => "anotherValue2"), |
||
521 | * ) |
||
522 | * or array("col1" => "value1", "col2" => "anotherValue1") |
||
523 | * |
||
524 | * @return \Phinx\Db\Table |
||
525 | */ |
||
526 | public function insert($data) |
||
540 | |||
541 | /** |
||
542 | * Creates a table from the object instance. |
||
543 | * |
||
544 | * @return void |
||
545 | */ |
||
546 | public function create() |
||
552 | |||
553 | /** |
||
554 | * Updates a table from the object instance. |
||
555 | * |
||
556 | * @throws \RuntimeException |
||
557 | * @return void |
||
558 | */ |
||
559 | public function update() |
||
565 | 15 | ||
566 | 15 | /** |
|
567 | * Commit the pending data waiting for insertion. |
||
568 | 15 | * |
|
569 | 15 | * @return void |
|
570 | 15 | */ |
|
571 | public function saveData() |
||
597 | |||
598 | 8 | /** |
|
599 | 8 | * Immediately truncates the table. This operation cannot be undone |
|
600 | * |
||
601 | * @return void |
||
602 | */ |
||
603 | public function truncate() |
||
604 | { |
||
605 | $this->getAdapter()->truncateTable($this->getName()); |
||
606 | } |
||
607 | 196 | ||
608 | /** |
||
609 | 196 | * Commits the table changes. |
|
610 | 196 | * |
|
611 | 196 | * If the table doesn't exist it is created otherwise it is updated. |
|
612 | 196 | * |
|
613 | * @return void |
||
614 | */ |
||
615 | public function save() |
||
625 | |||
626 | /** |
||
627 | 46 | * Executes all the pending actions for this table |
|
628 | 38 | * |
|
629 | 46 | * @param bool $exists Whether or not the table existed prior to executing this method |
|
630 | * @return void |
||
631 | 46 | */ |
|
632 | 6 | protected function executeActions($exists) |
|
656 | } |
||
657 |
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.