Complex classes like MySqlDb 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 MySqlDb, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 15 | class MySqlDb extends Db { |
||
| 16 | const MYSQL_DATE_FORMAT = 'Y-m-d H:i:s'; |
||
| 17 | |||
| 18 | /** |
||
| 19 | * @var string |
||
| 20 | */ |
||
| 21 | protected $dbname; |
||
| 22 | |||
| 23 | protected static $map = [ |
||
| 24 | Db::OP_GT => '>', |
||
| 25 | Db::OP_GTE => '>=', |
||
| 26 | Db::OP_LT => '<', |
||
| 27 | Db::OP_LTE => '<=', |
||
| 28 | Db::OP_LIKE => 'like', |
||
| 29 | Db::OP_AND => 'and', |
||
| 30 | Db::OP_OR => 'or', |
||
| 31 | ]; |
||
| 32 | |||
| 33 | /** |
||
| 34 | * {@inheritdoc} |
||
| 35 | */ |
||
| 36 | 6 | protected function dropTableDb($table, array $options = []) { |
|
| 43 | |||
| 44 | /** |
||
| 45 | * {@inheritdoc} |
||
| 46 | */ |
||
| 47 | 8 | protected function fetchTableDefDb($table) { |
|
| 65 | |||
| 66 | /** |
||
| 67 | * {@inheritdoc} |
||
| 68 | */ |
||
| 69 | 5 | protected function fetchColumnDefsDb($table) { |
|
| 70 | 5 | $rows = $this->get( |
|
| 71 | 5 | new Identifier('information_schema', 'COLUMNS'), |
|
| 72 | [ |
||
| 73 | 5 | 'TABLE_SCHEMA' => $this->getDbName(), |
|
| 74 | 5 | 'TABLE_NAME' => $this->prefixTable($table, false) |
|
| 75 | 5 | ], |
|
| 76 | [ |
||
| 77 | 5 | Db::OPTION_FETCH_MODE => PDO::FETCH_ASSOC, |
|
| 78 | 5 | 'order' => ['TABLE_NAME', 'ORDINAL_POSITION'] |
|
| 79 | 5 | ] |
|
| 80 | 5 | ); |
|
| 81 | |||
| 82 | 5 | $columns = []; |
|
| 83 | 5 | foreach ($rows as $row) { |
|
| 84 | 5 | $columnType = $row['COLUMN_TYPE']; |
|
| 85 | 5 | if ($columnType === 'tinyint(1)') { |
|
| 86 | 1 | $columnType = 'bool'; |
|
| 87 | 1 | } |
|
| 88 | 5 | $column = Db::typeDef($columnType); |
|
| 89 | 5 | if ($column === null) { |
|
| 90 | throw new \Exception("Unknown type '$columnType'.", 500); |
||
| 91 | } |
||
| 92 | |||
| 93 | 5 | $column['allowNull'] = strcasecmp($row['IS_NULLABLE'], 'YES') === 0; |
|
| 94 | |||
| 95 | 5 | if (($default = $row['COLUMN_DEFAULT']) !== null) { |
|
| 96 | 4 | $column['default'] = $this->forceType($default, $column['type']); |
|
| 97 | 4 | } |
|
| 98 | |||
| 99 | 5 | if ($row['EXTRA'] === 'auto_increment') { |
|
| 100 | 1 | $column['autoIncrement'] = true; |
|
| 101 | 1 | } |
|
| 102 | |||
| 103 | 5 | if ($row['COLUMN_KEY'] === 'PRI') { |
|
| 104 | 3 | $column['primary'] = true; |
|
| 105 | 3 | } |
|
| 106 | |||
| 107 | 5 | $columns[$row['COLUMN_NAME']] = $column; |
|
| 108 | 5 | } |
|
| 109 | |||
| 110 | 5 | return $columns; |
|
| 111 | } |
||
| 112 | |||
| 113 | /** |
||
| 114 | * {@inheritdoc} |
||
| 115 | */ |
||
| 116 | 72 | public function get($table, array $where, array $options = []) { |
|
| 121 | |||
| 122 | /** |
||
| 123 | * Build a sql select statement. |
||
| 124 | * |
||
| 125 | * @param string|Identifier $tableName The name of the main table. |
||
| 126 | * @param array $where The where filter. |
||
| 127 | * @param array $options An array of additional query options. |
||
| 128 | * @return string Returns the select statement as a string. |
||
| 129 | * @see Db::get() |
||
| 130 | */ |
||
| 131 | 76 | protected function buildSelect($tableName, array $where, array $options = []) { |
|
| 190 | |||
| 191 | /** |
||
| 192 | * Build a where clause from a where array. |
||
| 193 | * |
||
| 194 | * @param array $where There where string. |
||
| 195 | * This is an array in the form `['column' => 'value']` with more advanced options for non-equality comparisons. |
||
| 196 | * @param string $op The logical operator to join multiple field comparisons. |
||
| 197 | * @return string The where string. |
||
| 198 | */ |
||
| 199 | 78 | protected function buildWhere($where, $op = Db::OP_AND) { |
|
| 293 | |||
| 294 | /** |
||
| 295 | * Build a like expression. |
||
| 296 | * |
||
| 297 | * @param string $column The column name. |
||
| 298 | * @param mixed $value The right-hand value. |
||
| 299 | * @return string Returns the like expression. |
||
| 300 | * @internal param bool $quotevals Whether or not to quote the values. |
||
| 301 | */ |
||
| 302 | protected function buildLike($column, $value) { |
||
| 305 | |||
| 306 | /** |
||
| 307 | * Convert an array into a bracketed list suitable for MySQL clauses. |
||
| 308 | * |
||
| 309 | * @param array $row The row to expand. |
||
| 310 | * @param string $quote The quotes to surroud the items with. There are two special cases. |
||
| 311 | * ' (single quote) |
||
| 312 | * : The row will be passed through {@link PDO::quote()}. |
||
| 313 | * ` (backticks) |
||
| 314 | * : The row will be passed through {@link MySqlDb::backtick()}. |
||
| 315 | * @return string Returns the bracket list. |
||
| 316 | */ |
||
| 317 | 72 | public function bracketList($row, $quote = "'") { |
|
| 331 | |||
| 332 | |||
| 333 | /** |
||
| 334 | * Get the current database name. |
||
| 335 | * |
||
| 336 | * @return mixed |
||
| 337 | */ |
||
| 338 | 5 | private function getDbName() { |
|
| 344 | |||
| 345 | /** |
||
| 346 | * {@inheritdoc} |
||
| 347 | */ |
||
| 348 | 17 | protected function nativeDbType(array $type) { |
|
| 364 | |||
| 365 | /** |
||
| 366 | * Parse a column type string and return it in a way that is suitable for a create/alter table statement. |
||
| 367 | * |
||
| 368 | * @param string $typeString The string to parse. |
||
| 369 | * @return string Returns a canonical string. |
||
| 370 | */ |
||
| 371 | protected function columnTypeString($typeString) { |
||
| 414 | |||
| 415 | /** |
||
| 416 | * Get the indexes from the database. |
||
| 417 | * |
||
| 418 | * @param string $table The name of the table to get the indexes for. |
||
| 419 | * @return array|null |
||
| 420 | */ |
||
| 421 | 4 | protected function fetchIndexesDb($table = '') { |
|
| 457 | |||
| 458 | /** |
||
| 459 | * {@inheritdoc} |
||
| 460 | */ |
||
| 461 | protected function fetchTableNamesDb() { |
||
| 477 | |||
| 478 | /** |
||
| 479 | * {@inheritdoc} |
||
| 480 | */ |
||
| 481 | 15 | public function insert($table, array $row, array $options = []) { |
|
| 490 | |||
| 491 | /** |
||
| 492 | * Build an insert statement. |
||
| 493 | * |
||
| 494 | * @param string|Identifier $tableName The name of the table to insert to. |
||
| 495 | * @param array $row The row to insert. |
||
| 496 | * @param array $options An array of options for the insert. See {@link Db::insert} for the options. |
||
| 497 | * @return string Returns the the sql string of the insert statement. |
||
| 498 | */ |
||
| 499 | 32 | protected function buildInsert($tableName, array $row, $options = []) { |
|
| 518 | |||
| 519 | /** |
||
| 520 | * Build an upsert statement. |
||
| 521 | * |
||
| 522 | * An upsert statement is an insert on duplicate key statement in MySQL. |
||
| 523 | * |
||
| 524 | * @param string $tableName The name of the table to update. |
||
| 525 | * @param array $row The row to insert or update. |
||
| 526 | * @param array $options An array of additional query options. |
||
| 527 | * @return string Returns the upsert statement as a string. |
||
| 528 | */ |
||
| 529 | 2 | protected function buildUpsert($tableName, array $row, $options = []) { |
|
| 543 | |||
| 544 | /** |
||
| 545 | * {@inheritdoc} |
||
| 546 | */ |
||
| 547 | 54 | public function load($table, $rows, array $options = []) { |
|
| 572 | |||
| 573 | /** |
||
| 574 | * Make a valid PDO parameter name from a string. |
||
| 575 | * |
||
| 576 | * This method replaces invalid placeholder characters with underscores. |
||
| 577 | * |
||
| 578 | * @param string $name The name to replace. |
||
| 579 | * @return string |
||
| 580 | */ |
||
| 581 | 44 | protected function paramName($name) { |
|
| 585 | |||
| 586 | /** |
||
| 587 | * {@inheritdoc} |
||
| 588 | */ |
||
| 589 | 6 | public function update($table, array $set, array $where, array $options = []) { |
|
| 595 | |||
| 596 | /** |
||
| 597 | * Build a sql update statement. |
||
| 598 | * |
||
| 599 | * @param string|Identifier $tableName The name of the table to update. |
||
| 600 | * @param array $set An array of columns to set. |
||
| 601 | * @param array $where The where filter. |
||
| 602 | * @param array $options Additional options for the query. |
||
| 603 | * @return string Returns the update statement as a string. |
||
| 604 | */ |
||
| 605 | 2 | protected function buildUpdate($tableName, array $set, array $where, array $options = []) { |
|
| 625 | |||
| 626 | /** |
||
| 627 | * {@inheritdoc} |
||
| 628 | */ |
||
| 629 | 30 | public function delete($table, array $where, array $options = []) { |
|
| 644 | |||
| 645 | /** |
||
| 646 | * {@inheritdoc} |
||
| 647 | */ |
||
| 648 | 17 | protected function createTableDb(array $tableDef, array $options = []) { |
|
| 675 | |||
| 676 | /** |
||
| 677 | * Construct a column definition string from an array defintion. |
||
| 678 | * |
||
| 679 | * @param string $name The name of the column. |
||
| 680 | * @param array $cdef The column definition. |
||
| 681 | * @return string Returns a string representing the column definition. |
||
| 682 | */ |
||
| 683 | 17 | protected function columnDefString($name, array $cdef) { |
|
| 700 | |||
| 701 | /** |
||
| 702 | * Return the SDL string that defines an index. |
||
| 703 | * |
||
| 704 | * @param string $tableName The name of the table that the index is on. |
||
| 705 | * @param array $def The index defintion. This definition should have the following keys. |
||
| 706 | * |
||
| 707 | * columns |
||
| 708 | * : An array of columns in the index. |
||
| 709 | * type |
||
| 710 | * : One of "index", "unique", or "primary". |
||
| 711 | * @return null|string Returns the index string or null if the index is not correct. |
||
| 712 | */ |
||
| 713 | 17 | protected function indexDefString($tableName, array $def) { |
|
| 725 | |||
| 726 | /** |
||
| 727 | * {@inheritdoc} |
||
| 728 | */ |
||
| 729 | 4 | protected function alterTableDb(array $alterDef, array $options = []) { |
|
| 768 | |||
| 769 | /** |
||
| 770 | * Get an array of column orders so that added columns can be slotted into their correct spot. |
||
| 771 | * |
||
| 772 | * @param array $cdefs An array of column definitions. |
||
| 773 | * @return array Returns an array of column orders suitable for an `alter table` statement. |
||
| 774 | */ |
||
| 775 | 4 | private function getColumnOrders($cdefs) { |
|
| 785 | |||
| 786 | /** |
||
| 787 | * Force a value into the appropriate php type based on its SQL type. |
||
| 788 | * |
||
| 789 | * @param mixed $value The value to force. |
||
| 790 | * @param string $type The sqlite type name. |
||
| 791 | * @return mixed Returns $value cast to the appropriate type. |
||
| 792 | */ |
||
| 793 | 4 | protected function forceType($value, $type) { |
|
| 810 | |||
| 811 | 40 | public function quote($value, $column = '') { |
|
| 818 | } |
||
| 819 |
This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.
To visualize
will produce issues in the first and second line, while this second example
will produce no issues.