Complex classes like Schema 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 Schema, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 38 | class Schema extends BaseSchema implements ConstraintFinderInterface |
||
| 39 | { |
||
| 40 | use ViewFinderTrait; |
||
| 41 | use ConstraintFinderTrait; |
||
| 42 | |||
| 43 | private $_lastInsertID = null; |
||
| 44 | |||
| 45 | /** |
||
| 46 | * @var array map of DB errors and corresponding exceptions |
||
| 47 | * If left part is found in DB error message exception class from the right part is used. |
||
| 48 | */ |
||
| 49 | public $exceptionMap = [ |
||
| 50 | 'SQLSTATE[23' => 'yii\db\IntegrityException', |
||
| 51 | 'SQLSTATE[HY000]: General error: -803 violation of PRIMARY' => 'yii\db\IntegrityException', |
||
| 52 | ]; |
||
| 53 | public $reservedWords = [ |
||
| 54 | 'ADD', |
||
| 55 | 'ADMIN', |
||
| 56 | 'ALL', |
||
| 57 | 'ALTER', |
||
| 58 | 'AND', |
||
| 59 | 'ANY', |
||
| 60 | 'AS', |
||
| 61 | 'AT', |
||
| 62 | 'AVG', |
||
| 63 | 'BEGIN', |
||
| 64 | 'BETWEEN', |
||
| 65 | 'BIGINT', |
||
| 66 | 'BIT_LENGTH', |
||
| 67 | 'BLOB', |
||
| 68 | 'BOTH', |
||
| 69 | 'BOOLEAN', |
||
| 70 | 'BY', |
||
| 71 | 99 | 'CASE', |
|
| 72 | 'CAST', |
||
| 73 | 99 | 'CHAR', |
|
| 74 | 'CHAR_LENGTH', |
||
| 75 | 'CHARACTER', |
||
| 76 | 'CHARACTER_LENGTH', |
||
| 77 | 'CHECK', |
||
| 78 | 'CLOSE', |
||
| 79 | 2 | 'COLLATE', |
|
| 80 | 'COLUMN', |
||
| 81 | 2 | 'COMMIT', |
|
| 82 | 'CONNECT', |
||
| 83 | 'CONSTRAINT', |
||
| 84 | 157 | 'CORR', |
|
| 85 | 'COUNT', |
||
| 86 | 157 | 'COVAR_POP', |
|
| 87 | 'CREATE', |
||
| 88 | 'CROSS', |
||
| 89 | 'CURRENT', |
||
| 90 | 157 | 'CURRENT_CONNECTION', |
|
| 91 | 157 | 'CURRENT_DATE', |
|
| 92 | 43 | 'CURRENT_ROLE', |
|
| 93 | 'CURRENT_TIME', |
||
| 94 | 'CURRENT_TIMESTAMP', |
||
| 95 | 156 | 'CURRENT_TRANSACTION', |
|
| 96 | 'CURRENT_USER', |
||
| 97 | 'CURSOR', |
||
| 98 | 173 | 'DATE', |
|
| 99 | 'DAY', |
||
| 100 | 173 | 'DEC', |
|
| 101 | 6 | 'DECIMAL', |
|
| 102 | 'DECLARE', |
||
| 103 | 173 | 'DEFAULT', |
|
| 104 | 'DELETE', |
||
| 105 | 'DELETING', |
||
| 106 | 106 | 'DETERMINISTIC', |
|
| 107 | 'DISCONNECT', |
||
| 108 | 106 | 'DISTINCT', |
|
| 109 | 106 | 'DOUBLE', |
|
| 110 | 106 | 'DROP', |
|
| 111 | 104 | 'ELSE', |
|
| 112 | 104 | 'END', |
|
| 113 | 'ESCAPE', |
||
| 114 | 7 | 'EXECUTE', |
|
| 115 | 'EXISTS', |
||
| 116 | 'EXTERNAL', |
||
| 117 | 93 | 'EXRACT', |
|
| 118 | 'FALSE', |
||
| 119 | 93 | 'FETCH', |
|
| 120 | 'FILTER', |
||
| 121 | 'FLOAT', |
||
| 122 | 'FOR', |
||
| 123 | 'FOREIGN', |
||
| 124 | 'FROM', |
||
| 125 | 'FULL', |
||
| 126 | 'FUNCTION', |
||
| 127 | 93 | 'GDSCODE', |
|
| 128 | 'GLOBAL', |
||
| 129 | 93 | 'GRANT', |
|
| 130 | 'GROUP', |
||
| 131 | 'HAVING', |
||
| 132 | 'HOUR', |
||
| 133 | 'IN', |
||
| 134 | 'INDEX', |
||
| 135 | 'INNER', |
||
| 136 | 'INSENSITIVE', |
||
| 137 | 106 | 'INSERT', |
|
| 138 | 'INSERTING', |
||
| 139 | 106 | 'INT', |
|
| 140 | 106 | 'INTEGER', |
|
| 141 | 'INTO', |
||
| 142 | 'IS', |
||
| 143 | 'JOIN', |
||
| 144 | 'LEADING', |
||
| 145 | 106 | 'LEFT', |
|
| 146 | 106 | 'LIKE', |
|
| 147 | 'LONG', |
||
| 148 | 106 | 'LOWER', |
|
| 149 | 'MAX', |
||
| 150 | 'MAXIMUM_SEGMENT', |
||
| 151 | 'MERGE', |
||
| 152 | 'MIN', |
||
| 153 | 'MINUTE', |
||
| 154 | 'MONTH', |
||
| 155 | 'NATIONAL', |
||
| 156 | 106 | 'NATURAL', |
|
| 157 | 'NCHAR', |
||
| 158 | 'NO', |
||
| 159 | 'NOT', |
||
| 160 | 'NULL', |
||
| 161 | 'NUMERIC', |
||
| 162 | 'OCTET_LENGTH', |
||
| 163 | 'OF', |
||
| 164 | 'OFFSET', |
||
| 165 | 'ON', |
||
| 166 | 'OPEN', |
||
| 167 | 'OR', |
||
| 168 | 'ORDER', |
||
| 169 | 'OUTER', |
||
| 170 | 'OVER', |
||
| 171 | 'PARAMETER', |
||
| 172 | 'PASSWORD', |
||
| 173 | 'PLAN', |
||
| 174 | 106 | 'POSITION', |
|
| 175 | 'POST_EVENT', |
||
| 176 | 'PRECISION', |
||
| 177 | 'PRIMARY', |
||
| 178 | 'PROCEDURE', |
||
| 179 | 'RDB$DB_KEY', |
||
| 180 | 'RDB$RECORD_VERSION', |
||
| 181 | 'REAL', |
||
| 182 | 'RECORD_VERSION', |
||
| 183 | 'RECREATE', |
||
| 184 | 106 | 'RECURSIVE', |
|
| 185 | 'REFERENCES', |
||
| 186 | 106 | 'REGR_AVGX', |
|
| 187 | 'REGR_AVGY', |
||
| 188 | 106 | 'REGR_COUNT', |
|
| 189 | 106 | 'REGR_INTERCEPT', |
|
| 190 | 106 | 'REGR_R2', |
|
| 191 | 'REGR_SLOPE', |
||
| 192 | 'REGR_SXX', |
||
| 193 | 'REGR_SXY', |
||
| 194 | 'REGR_SYY', |
||
| 195 | 'RELEASE', |
||
| 196 | 'RETURN', |
||
| 197 | 'RETURNING_VALUES', |
||
| 198 | 'RETURNS', |
||
| 199 | 'REVOKE', |
||
| 200 | 'RIGHT', |
||
| 201 | 104 | 'ROLLBACK', |
|
| 202 | 'ROW', |
||
| 203 | 104 | 'ROWS', |
|
| 204 | 'ROW_COUNT', |
||
| 205 | 'SAVEPOINT', |
||
| 206 | 'SCROLL', |
||
| 207 | 104 | 'SECOND', |
|
| 208 | 104 | 'SELECT', |
|
| 209 | 104 | 'SENSITIVE', |
|
| 210 | 104 | 'SET', |
|
| 211 | 104 | 'SIMILAR', |
|
| 212 | 'SOME', |
||
| 213 | 104 | 'SQLCODE', |
|
| 214 | 104 | 'SQLSTATE', |
|
| 215 | 104 | 'START', |
|
| 216 | 87 | 'STDDEV_POP', |
|
| 217 | 87 | 'STDDEV_SAMP', |
|
| 218 | 79 | 'SUM', |
|
| 219 | 13 | 'TABLE', |
|
| 220 | 13 | 'THEN', |
|
| 221 | 'TIME', |
||
| 222 | 'TIMESTAMP', |
||
| 223 | 104 | 'TO', |
|
| 224 | 104 | 'TRAILING', |
|
| 225 | 104 | 'TRIGGER', |
|
| 226 | 'TRIM', |
||
| 227 | 'TRUE', |
||
| 228 | 104 | 'UNION', |
|
| 229 | 'UNIQUE', |
||
| 230 | 'UNKNOWN', |
||
| 231 | 'UPDATE', |
||
| 232 | 'UPDATING', |
||
| 233 | 'UPPER', |
||
| 234 | 'USER', |
||
| 235 | 104 | 'USING', |
|
| 236 | 'VALUE', |
||
| 237 | 104 | 'VALUES', |
|
| 238 | 'VARCHAR', |
||
| 239 | 'VARIABLE', |
||
| 240 | 'VARYING', |
||
| 241 | 'VAR_POP', |
||
| 242 | 'VAR_SAMP', |
||
| 243 | 'VIEW', |
||
| 244 | 'WHEN', |
||
| 245 | 'WHERE', |
||
| 246 | 104 | 'WHILE', |
|
| 247 | 'WITH', |
||
| 248 | 104 | 'YEAR', |
|
| 249 | 104 | ]; |
|
| 250 | 104 | ||
| 251 | 104 | /** |
|
| 252 | 104 | * @var array mapping from physical column types (keys) to abstract column types (values) |
|
| 253 | 104 | */ |
|
| 254 | public $typeMap = [ |
||
| 255 | 104 | 'bigint' => self::TYPE_BIGINT, |
|
| 256 | 'char' => self::TYPE_CHAR, |
||
| 257 | 104 | 'varchar' => self::TYPE_STRING, |
|
| 258 | 104 | 'timestamp' => self::TYPE_TIMESTAMP, |
|
| 259 | 'decimal' => self::TYPE_DECIMAL, |
||
| 260 | 63 | 'float' => self::TYPE_FLOAT, |
|
| 261 | 63 | 'blob' => self::TYPE_BINARY, |
|
| 262 | 'integer' => self::TYPE_INTEGER, |
||
| 263 | 'blob sub_type text' => self::TYPE_TEXT, |
||
| 264 | 63 | 'numeric' => self::TYPE_DECIMAL, |
|
| 265 | 'double precision' => self::TYPE_DOUBLE, |
||
| 266 | 104 | 'smallint' => self::TYPE_SMALLINT, |
|
| 267 | 103 | ]; |
|
| 268 | |||
| 269 | 104 | /** |
|
| 270 | * {@inheritdoc} |
||
| 271 | 104 | */ |
|
| 272 | protected function resolveTableName($name) |
||
| 278 | |||
| 279 | /** |
||
| 280 | * Creates a query builder for the database. |
||
| 281 | * This method may be overridden by child classes to create a DBMS-specific query builder. |
||
| 282 | * @return QueryBuilder query builder instance |
||
| 283 | */ |
||
| 284 | public function createQueryBuilder() |
||
| 288 | |||
| 289 | /** |
||
| 290 | 104 | * @inheritdoc |
|
| 291 | 104 | */ |
|
| 292 | 88 | public function createColumnSchemaBuilder($type, $length = null) |
|
| 296 | |||
| 297 | 104 | public function quoteSimpleTableName($name) |
|
| 310 | 16 | ||
| 311 | 16 | public function quoteSimpleColumnName($name) |
|
| 318 | 3 | ||
| 319 | 3 | protected function loadTableSchema($name) |
|
| 328 | 46 | ||
| 329 | public function getPdoType($data) |
||
| 343 | |||
| 344 | 104 | /** |
|
| 345 | * |
||
| 346 | 104 | * @param TableSchema $table |
|
| 347 | 104 | * @param string $name |
|
| 348 | 104 | */ |
|
| 349 | 104 | protected function resolveTableNames($table, $name) |
|
| 361 | 15 | ||
| 362 | /** |
||
| 363 | 63 | * Collects the table column metadata. |
|
| 364 | * |
||
| 365 | * @param TableSchema $table the table metadata |
||
| 366 | * @return boolean whether the table exists in the database |
||
| 367 | 104 | */ |
|
| 368 | protected function findColumns($table) |
||
| 452 | |||
| 453 | /** |
||
| 454 | * @return ColumnSchema |
||
| 455 | * @throws \yii\base\InvalidConfigException |
||
| 456 | */ |
||
| 457 | protected function createColumnSchema() |
||
| 461 | 1 | ||
| 462 | 1 | /** |
|
| 463 | 1 | * Creates a table column. |
|
| 464 | * |
||
| 465 | 1 | * @param array $column column metadata |
|
| 466 | * @return ColumnSchema normalized column metadata |
||
| 467 | */ |
||
| 468 | protected function loadColumnSchema($column) |
||
| 591 | |||
| 592 | /** |
||
| 593 | * Collects the foreign key column details for the given table. |
||
| 594 | * |
||
| 595 | * @param TableSchema $table the table metadata |
||
| 596 | */ |
||
| 597 | protected function findConstraints($table) |
||
| 636 | |||
| 637 | protected function findTableNames($schema = '') |
||
| 656 | |||
| 657 | /** |
||
| 658 | * Returns all unique indexes for the given table. |
||
| 659 | * Each array element is of the following structure: |
||
| 660 | * |
||
| 661 | * ~~~ |
||
| 662 | * [ |
||
| 663 | * 'IndexName1' => ['col1' [, ...]], |
||
| 664 | * 'IndexName2' => ['col2' [, ...]], |
||
| 665 | * ] |
||
| 666 | * ~~~ |
||
| 667 | * |
||
| 668 | * @param TableSchema $table the table metadata |
||
| 669 | * @return array all unique indexes for the given table. |
||
| 670 | * @since 2.0.4 |
||
| 671 | */ |
||
| 672 | public function findUniqueIndexes($table) |
||
| 689 | |||
| 690 | /** |
||
| 691 | * Sets the isolation level of the current transaction. |
||
| 692 | * @param string $level The transaction isolation level to use for this transaction. |
||
| 693 | * This can be one of [[Transaction::READ_UNCOMMITTED]], [[Transaction::READ_COMMITTED]], [[Transaction::REPEATABLE_READ]] |
||
| 694 | * and [[Transaction::SERIALIZABLE]] but also a string containing DBMS specific syntax to be used |
||
| 695 | * after `SET TRANSACTION ISOLATION LEVEL`. |
||
| 696 | * @see http://en.wikipedia.org/wiki/Isolation_%28database_systems%29#Isolation_levels |
||
| 697 | */ |
||
| 698 | public function setTransactionIsolationLevel($level) |
||
| 710 | |||
| 711 | /** |
||
| 712 | * @inheritdoc |
||
| 713 | */ |
||
| 714 | public function insert($table, $columns) |
||
| 746 | |||
| 747 | /** |
||
| 748 | * @inheritdoc |
||
| 749 | */ |
||
| 750 | public function getLastInsertID($sequenceName = '') |
||
| 765 | |||
| 766 | protected function loadTablePrimaryKey($tableName) |
||
| 796 | |||
| 797 | protected function loadTableUniques($tableName) |
||
| 828 | |||
| 829 | protected function loadTableChecks($tableName) |
||
| 874 | |||
| 875 | protected function loadTableDefaultValues($tableName) |
||
| 879 | |||
| 880 | protected function loadTableForeignKeys($tableName) |
||
| 884 | |||
| 885 | protected function loadTableIndexes($tableName) |
||
| 889 | |||
| 890 | protected function findViewNames($schema = '') |
||
| 893 | } |
||
| 894 |
Let’s assume that you have a directory layout like this:
. |-- OtherDir | |-- Bar.php | `-- Foo.php `-- SomeDir `-- Foo.phpand let’s assume the following content of
Bar.php:If both files
OtherDir/Foo.phpandSomeDir/Foo.phpare loaded in the same runtime, you will see a PHP error such as the following:PHP Fatal error: Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.phpHowever, as
OtherDir/Foo.phpdoes not necessarily have to be loaded and the error is only triggered if it is loaded beforeOtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias: