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 Model 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 Model, and based on these observations, apply Extract Interface, too.
| 1 | <?php  | 
            ||
| 10 | class Model  | 
            ||
| 11 | { | 
            ||
| 12 | /**  | 
            ||
| 13 | * The DBAL connection  | 
            ||
| 14 | *  | 
            ||
| 15 | * @var \Doctrine\DBAL\Connection  | 
            ||
| 16 | */  | 
            ||
| 17 | protected $conn = null;  | 
            ||
| 18 | |||
| 19 | /**  | 
            ||
| 20 | * Shortcut for the return of getSchemaManager()  | 
            ||
| 21 | *  | 
            ||
| 22 | * @var \Doctrine\DBAL\Schema\AbstractSchemaManager  | 
            ||
| 23 | */  | 
            ||
| 24 | protected $sm = null;  | 
            ||
| 25 | |||
| 26 | /**  | 
            ||
| 27 | * Table-Name  | 
            ||
| 28 | *  | 
            ||
| 29 | * @var string  | 
            ||
| 30 | */  | 
            ||
| 31 | protected $table_name = '';  | 
            ||
| 32 | |||
| 33 | /**  | 
            ||
| 34 | * Quoted Table-Name  | 
            ||
| 35 | *  | 
            ||
| 36 | * @var string  | 
            ||
| 37 | */  | 
            ||
| 38 | protected $quoted_table_name = '';  | 
            ||
| 39 | |||
| 40 | /**  | 
            ||
| 41 | * Array with the Columns  | 
            ||
| 42 | *  | 
            ||
| 43 | * @var \Doctrine\DBAL\Schema\Column[]  | 
            ||
| 44 | */  | 
            ||
| 45 | protected $columns = [];  | 
            ||
| 46 | |||
| 47 | /**  | 
            ||
| 48 | * Shortcut with Column-Types  | 
            ||
| 49 | *  | 
            ||
| 50 | * @var array  | 
            ||
| 51 | */  | 
            ||
| 52 | protected $column_types = [];  | 
            ||
| 53 | |||
| 54 | /**  | 
            ||
| 55 | * Caching variable if the table has an auto increment column  | 
            ||
| 56 | *  | 
            ||
| 57 | * @var bool  | 
            ||
| 58 | */  | 
            ||
| 59 | protected $has_autoincrement = null;  | 
            ||
| 60 | |||
| 61 | /**  | 
            ||
| 62 | * Original return type for the read-method  | 
            ||
| 63 | *  | 
            ||
| 64 | * @var string  | 
            ||
| 65 | */  | 
            ||
| 66 | const READ_RETURN_ORIGINAL = 'original';  | 
            ||
| 67 | |||
| 68 | /**  | 
            ||
| 69 | * Simple return type for the read-method  | 
            ||
| 70 | *  | 
            ||
| 71 | * @var string  | 
            ||
| 72 | */  | 
            ||
| 73 | const READ_RETURN_SIMPLE = 'simple';  | 
            ||
| 74 | |||
| 75 | /**  | 
            ||
| 76 | * Complex return type for the read-method  | 
            ||
| 77 | *  | 
            ||
| 78 | * @var string  | 
            ||
| 79 | */  | 
            ||
| 80 | const READ_RETURN_COMPLEX = 'complex';  | 
            ||
| 81 | |||
| 82 | /**  | 
            ||
| 83 | * constructor  | 
            ||
| 84 | *  | 
            ||
| 85 | * @param string $table_name  | 
            ||
| 86 | * @param Connection $conn  | 
            ||
| 87 | */  | 
            ||
| 88 | public function __construct($table_name, \Doctrine\DBAL\Connection $conn)  | 
            ||
| 102 | |||
| 103 | /**  | 
            ||
| 104 | * Tells of the table has an auto increment column  | 
            ||
| 105 | *  | 
            ||
| 106 | * @return boolean  | 
            ||
| 107 | */  | 
            ||
| 108 | public function hasAutoIncrement()  | 
            ||
| 121 | |||
| 122 | /**  | 
            ||
| 123 | * Returns the Column with $column_name  | 
            ||
| 124 | *  | 
            ||
| 125 | * @param string $column_name  | 
            ||
| 126 | *  | 
            ||
| 127 | * @return \Doctrine\DBAL\Schema\Column or null if the Column doesn't exist  | 
            ||
| 128 | */  | 
            ||
| 129 | protected function getColumn($column_name)  | 
            ||
| 133 | |||
| 134 | /**  | 
            ||
| 135 | * Creates a new datarow  | 
            ||
| 136 | *  | 
            ||
| 137 | * @param array $data  | 
            ||
| 138 | *  | 
            ||
| 139 | * @return boolean|string false on error, true on success or an string with the last insert id if the table has an auto increment column  | 
            ||
| 140 | */  | 
            ||
| 141 | public function create(array $data)  | 
            ||
| 157 | |||
| 158 | /**  | 
            ||
| 159 | * read $columns from $table_name  | 
            ||
| 160 | *  | 
            ||
| 161 | * @param array $columns  | 
            ||
| 162 | * @param array $filters  | 
            ||
| 163 | * @param array $limit  | 
            ||
| 164 | * @param array $order_by  | 
            ||
| 165 | * @param string $return_type  | 
            ||
| 166 | *  | 
            ||
| 167 | * @return array  | 
            ||
| 168 | */  | 
            ||
| 169 | public function read(array $columns = [], array $filters = [], array $limit = [], array $order_by = [], $return_type = self::READ_RETURN_COMPLEX)  | 
            ||
| 232 | |||
| 233 | /**  | 
            ||
| 234 | * Update table rows  | 
            ||
| 235 | *  | 
            ||
| 236 | * @param array $data  | 
            ||
| 237 | * @param array $filters  | 
            ||
| 238 | *  | 
            ||
| 239 | * @return integer The number of rows  | 
            ||
| 240 | */  | 
            ||
| 241 | public function update(array $data, array $filters = [])  | 
            ||
| 253 | |||
| 254 | /**  | 
            ||
| 255 | * Delete rows  | 
            ||
| 256 | *  | 
            ||
| 257 | * @param array $filters  | 
            ||
| 258 | *  | 
            ||
| 259 | * @return integer The number of rows  | 
            ||
| 260 | */  | 
            ||
| 261 | public function delete(array $filters = [])  | 
            ||
| 267 | |||
| 268 | /**  | 
            ||
| 269 | * copy some records and maybe change some values  | 
            ||
| 270 | *  | 
            ||
| 271 | * @param array $filters  | 
            ||
| 272 | * @param array $limit  | 
            ||
| 273 | * @param array $order_by  | 
            ||
| 274 | * @param array $changes  | 
            ||
| 275 | *  | 
            ||
| 276 | * @return array the result of each $this->create()  | 
            ||
| 277 | */  | 
            ||
| 278 | public function copy(array $filters = [], array $limit = [], array $order_by = [], array $changes = [])  | 
            ||
| 299 | |||
| 300 | /**  | 
            ||
| 301 | * Builds the WHERE clause from $filter  | 
            ||
| 302 | *  | 
            ||
| 303 | * @param QueryBuilder $qb  | 
            ||
| 304 | * @param array $filters should be an array with arrays wich contains 3 datas  | 
            ||
| 305 | * [  | 
            ||
| 306 | * ['column_name', 'expr_type', 'value'],  | 
            ||
| 307 | * [],  | 
            ||
| 308 | * ...  | 
            ||
| 309 | * ]  | 
            ||
| 310 | * expr_types: 'eq', 'neq', 'lt', 'lte', 'gt', 'gte', 'like', 'in', 'notIn', 'notLike'  | 
            ||
| 311 | *  | 
            ||
| 312 | * @return self  | 
            ||
| 313 | */  | 
            ||
| 314 | protected function buildWhere(QueryBuilder $qb, array $filters = [])  | 
            ||
| 345 | |||
| 346 | /**  | 
            ||
| 347 | * Build up dynamilcy the LIMIT part  | 
            ||
| 348 | *  | 
            ||
| 349 | * @param QueryBuilder $qb  | 
            ||
| 350 | * @param array $limit  | 
            ||
| 351 | *  | 
            ||
| 352 | * @return self  | 
            ||
| 353 | */  | 
            ||
| 354 | protected function buildLimit(QueryBuilder $qb, array $limit = [])  | 
            ||
| 367 | |||
| 368 | /**  | 
            ||
| 369 | * Builds the ORDER BY part  | 
            ||
| 370 | *  | 
            ||
| 371 | * @param QueryBuilder $qb  | 
            ||
| 372 | * @param array $order_by  | 
            ||
| 373 | *  | 
            ||
| 374 | * @return self  | 
            ||
| 375 | */  | 
            ||
| 376 | protected function buildOrderBy(QueryBuilder $qb, array $order_by = [])  | 
            ||
| 396 | |||
| 397 | /**  | 
            ||
| 398 | * Returns the table-Name  | 
            ||
| 399 | *  | 
            ||
| 400 | * @return string  | 
            ||
| 401 | */  | 
            ||
| 402 | public function getTableName()  | 
            ||
| 406 | |||
| 407 | /**  | 
            ||
| 408 | * List all possible expression types  | 
            ||
| 409 | *  | 
            ||
| 410 | * @return string[]  | 
            ||
| 411 | */  | 
            ||
| 412 | public function getExpressionTypes()  | 
            ||
| 416 | |||
| 417 | /**  | 
            ||
| 418 | * List all possible column names  | 
            ||
| 419 | * @return string[]  | 
            ||
| 420 | */  | 
            ||
| 421 | public function getColumnNames()  | 
            ||
| 425 | |||
| 426 | /**  | 
            ||
| 427 | * return true if the column type of $column_name is a simple type like string, integer, ...  | 
            ||
| 428 | * @param string $column_name  | 
            ||
| 429 | * @return boolean  | 
            ||
| 430 | */  | 
            ||
| 431 | public function isSimpleType($column_name)  | 
            ||
| 435 | }  | 
            ||
| 436 | 
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.
Both the
$myVarassignment in line 1 and the$higherassignment in line 2 are dead. The first because$myVaris never used and the second because$higheris always overwritten for every possible time line.