Complex classes like Database 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 Database, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 13 | class Database |
||
| 14 | { |
||
| 15 | /** |
||
| 16 | * @var EntityManager |
||
| 17 | */ |
||
| 18 | private static $em; |
||
| 19 | private static $connection; |
||
| 20 | public static $utcDateTimeClass; |
||
| 21 | |||
| 22 | /** |
||
| 23 | * @param EntityManager $em |
||
| 24 | */ |
||
| 25 | public function setManager($em) |
||
| 29 | |||
| 30 | /** |
||
| 31 | * @param Connection $connection |
||
| 32 | */ |
||
| 33 | public function setConnection(Connection $connection) |
||
| 37 | |||
| 38 | /** |
||
| 39 | * @return Connection |
||
| 40 | */ |
||
| 41 | public function getConnection() |
||
| 45 | |||
| 46 | /** |
||
| 47 | * @return EntityManager |
||
| 48 | */ |
||
| 49 | public static function getManager() |
||
| 53 | |||
| 54 | /** |
||
| 55 | * Returns the name of the main database. |
||
| 56 | * |
||
| 57 | * @return string |
||
| 58 | */ |
||
| 59 | public static function get_main_database() |
||
| 63 | |||
| 64 | /** |
||
| 65 | * Get main table |
||
| 66 | * |
||
| 67 | * @param string $table |
||
| 68 | * |
||
| 69 | * @return mixed |
||
| 70 | */ |
||
| 71 | public static function get_main_table($table) |
||
| 75 | |||
| 76 | /** |
||
| 77 | * Get course table |
||
| 78 | * |
||
| 79 | * @param string $table |
||
| 80 | * |
||
| 81 | * @return string |
||
| 82 | */ |
||
| 83 | public static function get_course_table($table) |
||
| 87 | |||
| 88 | /** |
||
| 89 | * Counts the number of rows in a table |
||
| 90 | * @param string $table The table of which the rows should be counted |
||
| 91 | * |
||
| 92 | * @return int The number of rows in the given table. |
||
| 93 | * @deprecated |
||
| 94 | */ |
||
| 95 | public static function count_rows($table) |
||
| 101 | |||
| 102 | /** |
||
| 103 | * Returns the number of affected rows in the last database operation. |
||
| 104 | * @param Statement $result |
||
| 105 | * |
||
| 106 | * @return int |
||
| 107 | */ |
||
| 108 | public static function affected_rows(Statement $result) |
||
| 112 | |||
| 113 | /** |
||
| 114 | * @return string |
||
| 115 | */ |
||
| 116 | public static function getUTCDateTimeTypeClass() |
||
| 121 | |||
| 122 | /** |
||
| 123 | * Connect to the database sets the entity manager. |
||
| 124 | * |
||
| 125 | * @param array $params |
||
| 126 | * @param string $sysPath |
||
| 127 | * @param string $entityRootPath |
||
| 128 | * |
||
| 129 | * @throws \Doctrine\ORM\ORMException |
||
| 130 | */ |
||
| 131 | public function connect($params = array(), $sysPath = '', $entityRootPath = '') |
||
| 132 | { |
||
| 133 | $config = self::getDoctrineConfig($entityRootPath); |
||
| 134 | $config->setAutoGenerateProxyClasses(true); |
||
| 135 | |||
| 136 | $config->setEntityNamespaces( |
||
| 137 | array( |
||
| 138 | 'ChamiloUserBundle' => 'Chamilo\UserBundle\Entity', |
||
| 139 | 'ChamiloCoreBundle' => 'Chamilo\CoreBundle\Entity', |
||
| 140 | 'ChamiloCourseBundle' => 'Chamilo\CourseBundle\Entity' |
||
| 141 | ) |
||
| 142 | ); |
||
| 143 | |||
| 144 | $params['charset'] = 'utf8'; |
||
| 145 | $entityManager = EntityManager::create($params, $config); |
||
| 146 | $sysPath = !empty($sysPath) ? $sysPath : api_get_path(SYS_PATH); |
||
| 147 | |||
| 148 | // Registering Constraints |
||
| 149 | AnnotationRegistry::registerAutoloadNamespace( |
||
| 150 | 'Symfony\Component\Validator\Constraint', |
||
| 151 | $sysPath."vendor/symfony/validator" |
||
| 152 | ); |
||
| 153 | |||
| 154 | AnnotationRegistry::registerFile( |
||
| 155 | $sysPath."vendor/symfony/doctrine-bridge/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php" |
||
| 156 | ); |
||
| 157 | |||
| 158 | // Registering gedmo extensions |
||
| 159 | AnnotationRegistry::registerAutoloadNamespace( |
||
| 160 | 'Gedmo\Mapping\Annotation', |
||
| 161 | $sysPath."vendor/gedmo/doctrine-extensions/lib" |
||
| 162 | ); |
||
| 163 | |||
| 164 | Type::overrideType( |
||
| 165 | Type::DATETIME, |
||
| 166 | self::getUTCDateTimeTypeClass() |
||
| 167 | ); |
||
| 168 | |||
| 169 | $listener = new \Gedmo\Timestampable\TimestampableListener(); |
||
| 170 | $entityManager->getEventManager()->addEventSubscriber($listener); |
||
| 171 | |||
| 172 | $listener = new \Gedmo\Tree\TreeListener(); |
||
| 173 | $entityManager->getEventManager()->addEventSubscriber($listener); |
||
| 174 | |||
| 175 | $listener = new \Gedmo\Sortable\SortableListener(); |
||
| 176 | $entityManager->getEventManager()->addEventSubscriber($listener); |
||
| 177 | $connection = $entityManager->getConnection(); |
||
| 178 | $connection->executeQuery('set sql_mode=""'); |
||
| 179 | $this->setConnection($connection); |
||
| 180 | $this->setManager($entityManager); |
||
| 181 | } |
||
| 182 | |||
| 183 | /** |
||
| 184 | * Escape MySQL wildchars _ and % in LIKE search |
||
| 185 | * @param string $text The string to escape |
||
| 186 | * |
||
| 187 | * @return string The escaped string |
||
| 188 | */ |
||
| 189 | public static function escape_sql_wildcards($text) |
||
| 196 | |||
| 197 | /** |
||
| 198 | * Escapes a string to insert into the database as text |
||
| 199 | * |
||
| 200 | * @param string $string |
||
| 201 | * |
||
| 202 | * @return string |
||
| 203 | */ |
||
| 204 | public static function escape_string($string) |
||
| 210 | |||
| 211 | /** |
||
| 212 | * Gets the array from a SQL result (as returned by Database::query) |
||
| 213 | * |
||
| 214 | * @param Statement $result |
||
| 215 | * @param string $option Optional: "ASSOC","NUM" or "BOTH" |
||
| 216 | * |
||
| 217 | * @return array|mixed |
||
| 218 | */ |
||
| 219 | public static function fetch_array(Statement $result, $option = 'BOTH') |
||
| 227 | |||
| 228 | /** |
||
| 229 | * Gets an associative array from a SQL result (as returned by Database::query). |
||
| 230 | * |
||
| 231 | * @param Statement $result |
||
| 232 | * |
||
| 233 | * @return array |
||
| 234 | */ |
||
| 235 | public static function fetch_assoc(Statement $result) |
||
| 239 | |||
| 240 | /** |
||
| 241 | * Gets the next row of the result of the SQL query |
||
| 242 | * (as returned by Database::query) in an object form |
||
| 243 | * |
||
| 244 | * @param Statement $result |
||
| 245 | * |
||
| 246 | * @return mixed |
||
| 247 | */ |
||
| 248 | public static function fetch_object(Statement $result) |
||
| 252 | |||
| 253 | /** |
||
| 254 | * Gets the array from a SQL result (as returned by Database::query) |
||
| 255 | * help achieving database independence |
||
| 256 | * |
||
| 257 | * @param Statement $result |
||
| 258 | * |
||
| 259 | * @return mixed |
||
| 260 | */ |
||
| 261 | public static function fetch_row(Statement $result) |
||
| 265 | |||
| 266 | /** |
||
| 267 | * Frees all the memory associated with the provided result identifier. |
||
| 268 | * @return bool Returns TRUE on success or FALSE on failure. |
||
| 269 | * Notes: Use this method if you are concerned about how much memory is being used for queries that return large result sets. |
||
| 270 | * Anyway, all associated result memory is automatically freed at the end of the script's execution. |
||
| 271 | */ |
||
| 272 | public static function free_result(Statement $result) |
||
| 273 | { |
||
| 274 | $result->closeCursor(); |
||
| 275 | } |
||
| 276 | |||
| 277 | /** |
||
| 278 | * Gets the ID of the last item inserted into the database |
||
| 279 | * |
||
| 280 | * @return string |
||
| 281 | */ |
||
| 282 | public static function insert_id() |
||
| 286 | |||
| 287 | /** |
||
| 288 | * @param Statement $result |
||
| 289 | * |
||
| 290 | * @return int |
||
| 291 | */ |
||
| 292 | public static function num_rows(Statement $result) |
||
| 296 | |||
| 297 | /** |
||
| 298 | * Acts as the relative *_result() function of most DB drivers and fetches a |
||
| 299 | * specific line and a field |
||
| 300 | * |
||
| 301 | * @param Statement $resource |
||
| 302 | * @param int $row |
||
| 303 | * @param string $field |
||
| 304 | * |
||
| 305 | * @return mixed |
||
| 306 | */ |
||
| 307 | public static function result(Statement $resource, $row, $field = '') |
||
| 315 | |||
| 316 | /** |
||
| 317 | * @param string $query |
||
| 318 | * |
||
| 319 | * @return Statement |
||
| 320 | * |
||
| 321 | * @throws \Doctrine\DBAL\DBALException |
||
| 322 | */ |
||
| 323 | public static function query($query) |
||
| 342 | |||
| 343 | /** |
||
| 344 | * @param string $option |
||
| 345 | * |
||
| 346 | * @return int |
||
| 347 | */ |
||
| 348 | public static function customOptionToDoctrineOption($option) |
||
| 363 | |||
| 364 | /** |
||
| 365 | * Stores a query result into an array. |
||
| 366 | * |
||
| 367 | * @author Olivier Brouckaert |
||
| 368 | * @param Statement $result - the return value of the query |
||
| 369 | * @param string $option BOTH, ASSOC, or NUM |
||
| 370 | * |
||
| 371 | * @return array - the value returned by the query |
||
| 372 | */ |
||
| 373 | public static function store_result(Statement $result, $option = 'BOTH') |
||
| 377 | |||
| 378 | /** |
||
| 379 | * Database insert |
||
| 380 | * @param string $table_name |
||
| 381 | * @param array $attributes |
||
| 382 | * @param bool $show_query |
||
| 383 | * |
||
| 384 | * @return bool|int |
||
| 385 | */ |
||
| 386 | public static function insert($table_name, $attributes, $show_query = false) |
||
| 413 | |||
| 414 | /** |
||
| 415 | * @param string $table_name use Database::get_main_table |
||
| 416 | * @param array $attributes Values to updates |
||
| 417 | * Example: $params['name'] = 'Julio'; $params['lastname'] = 'Montoya'; |
||
| 418 | * @param array $where_conditions where conditions i.e array('id = ?' =>'4') |
||
| 419 | * @param bool $show_query |
||
| 420 | * |
||
| 421 | * @return bool|int |
||
| 422 | */ |
||
| 423 | public static function update( |
||
| 464 | |||
| 465 | /** |
||
| 466 | * Experimental useful database finder |
||
| 467 | * @todo lot of stuff to do here |
||
| 468 | * @todo known issues, it doesn't work when using LIKE conditions |
||
| 469 | * @example array('where'=> array('course_code LIKE "?%"')) |
||
| 470 | * @example array('where'=> array('type = ? AND category = ?' => array('setting', 'Plugins')) |
||
| 471 | * @example array('where'=> array('name = "Julio" AND lastname = "montoya"')) |
||
| 472 | */ |
||
| 473 | public static function select($columns, $table_name, $conditions = array(), $type_result = 'all', $option = 'ASSOC') |
||
| 506 | |||
| 507 | /** |
||
| 508 | * Parses WHERE/ORDER conditions i.e array('where'=>array('id = ?' =>'4'), 'order'=>'id DESC')) |
||
| 509 | * @todo known issues, it doesn't work when using |
||
| 510 | * LIKE conditions example: array('where'=>array('course_code LIKE "?%"')) |
||
| 511 | * @param array $conditions |
||
| 512 | */ |
||
| 513 | public static function parse_conditions($conditions) |
||
| 607 | |||
| 608 | /** |
||
| 609 | * @param array $conditions |
||
| 610 | * |
||
| 611 | * @return string |
||
| 612 | */ |
||
| 613 | public static function parse_where_conditions($conditions) |
||
| 617 | |||
| 618 | /** |
||
| 619 | * @param string $table_name |
||
| 620 | * @param array $where_conditions |
||
| 621 | * @param bool $show_query |
||
| 622 | * |
||
| 623 | * @return int |
||
| 624 | */ |
||
| 625 | public static function delete($table_name, $where_conditions, $show_query = false) |
||
| 635 | |||
| 636 | /** |
||
| 637 | * Get Doctrine configuration |
||
| 638 | * @param string $path |
||
| 639 | * |
||
| 640 | * @return \Doctrine\ORM\Configuration |
||
| 641 | */ |
||
| 642 | public static function getDoctrineConfig($path) |
||
| 665 | |||
| 666 | /** |
||
| 667 | * @param string $table |
||
| 668 | * |
||
| 669 | * @return bool |
||
| 670 | */ |
||
| 671 | public static function tableExists($table) |
||
| 675 | } |
||
| 676 |
The
EntityManagermight become unusable for example if a transaction is rolled back and it gets closed. Let’s assume that somewhere in your application, or in a third-party library, there is code such as the following:If that code throws an exception and the
EntityManageris closed. Any other code which depends on the same instance of theEntityManagerduring this request will fail.On the other hand, if you instead inject the
ManagerRegistry, thegetManager()method guarantees that you will always get a usable manager instance.