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 Database_Core 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_Core, and based on these observations, apply Extract Interface, too.
1 | <?php defined('SYSPATH') or die('No direct access allowed.'); |
||
12 | class Database_Core |
||
13 | { |
||
14 | |||
15 | // Database instances |
||
16 | public static $instances = array(); |
||
17 | |||
18 | // Global benchmark |
||
19 | public static $benchmarks = array(); |
||
20 | |||
21 | // Configuration |
||
22 | protected $config = array( |
||
23 | 'benchmark' => true, |
||
24 | 'persistent' => false, |
||
25 | 'connection' => '', |
||
26 | 'character_set' => 'utf8', |
||
27 | 'table_prefix' => '', |
||
28 | 'object' => true, |
||
29 | 'cache' => false, |
||
30 | 'escape' => true, |
||
31 | ); |
||
32 | |||
33 | // Database driver object |
||
34 | protected $driver; |
||
35 | protected $link; |
||
36 | |||
37 | // Un-compiled parts of the SQL query |
||
38 | protected $select = array(); |
||
39 | protected $set = array(); |
||
40 | protected $from = array(); |
||
41 | protected $join = array(); |
||
42 | protected $where = array(); |
||
43 | protected $orderby = array(); |
||
44 | protected $order = array(); |
||
45 | protected $groupby = array(); |
||
46 | protected $having = array(); |
||
47 | protected $distinct = false; |
||
48 | protected $limit = false; |
||
49 | protected $offset = false; |
||
50 | protected $last_query = ''; |
||
51 | |||
52 | // Stack of queries for push/pop |
||
53 | protected $query_history = array(); |
||
54 | |||
55 | /** |
||
56 | * Returns a singleton instance of Database. |
||
57 | * |
||
58 | * @param mixed configuration array or DSN |
||
59 | * @return Database_Core |
||
60 | */ |
||
61 | View Code Duplication | public static function & instance($name = 'default', $config = null) |
|
70 | |||
71 | /** |
||
72 | * Returns the name of a given database instance. |
||
73 | * |
||
74 | * @param Database instance of Database |
||
75 | * @return string |
||
76 | */ |
||
77 | public static function instance_name(Database $db) |
||
81 | |||
82 | /** |
||
83 | * Sets up the database configuration, loads the Database_Driver. |
||
84 | * |
||
85 | * @throws Kohana_Database_Exception |
||
86 | */ |
||
87 | public function __construct($config = array()) |
||
195 | |||
196 | /** |
||
197 | * Simple connect method to get the database queries up and running. |
||
198 | * |
||
199 | * @return void |
||
200 | */ |
||
201 | public function connect() |
||
214 | |||
215 | /** |
||
216 | * Runs a query into the driver and returns the result. |
||
217 | * |
||
218 | * @param string SQL query to execute |
||
219 | * @return Database_Result |
||
220 | */ |
||
221 | public function query($sql = '') |
||
256 | |||
257 | /** |
||
258 | * Selects the column names for a database query. |
||
259 | * |
||
260 | * @param string string or array of column names to select |
||
261 | * @return Database_Core This Database object. |
||
262 | */ |
||
263 | public function select($sql = '*') |
||
296 | |||
297 | /** |
||
298 | * Selects the from table(s) for a database query. |
||
299 | * |
||
300 | * @param string string or array of tables to select |
||
301 | * @param string|boolean $sql |
||
302 | * @return Database_Core This Database object. |
||
303 | */ |
||
304 | public function from($sql) |
||
338 | |||
339 | /** |
||
340 | * Generates the JOIN portion of the query. |
||
341 | * |
||
342 | * @param string table name |
||
343 | * @param string|array where key or array of key => value pairs |
||
344 | * @param string where value |
||
345 | * @param string type of join |
||
346 | * @return Database_Core This Database object. |
||
347 | */ |
||
348 | public function join($table, $key, $value = null, $type = '') |
||
408 | |||
409 | |||
410 | /** |
||
411 | * Selects the where(s) for a database query. |
||
412 | * |
||
413 | * @param string|array key name or array of key => value pairs |
||
414 | * @param string value to match with key |
||
415 | * @param boolean disable quoting of WHERE clause |
||
416 | * @return Database_Core This Database object. |
||
417 | */ |
||
418 | View Code Duplication | public function where($key, $value = null, $quote = true) |
|
436 | |||
437 | /** |
||
438 | * Selects the or where(s) for a database query. |
||
439 | * |
||
440 | * @param string|array key name or array of key => value pairs |
||
441 | * @param string value to match with key |
||
442 | * @param boolean disable quoting of WHERE clause |
||
443 | * @return Database_Core This Database object. |
||
444 | */ |
||
445 | View Code Duplication | public function orwhere($key, $value = null, $quote = true) |
|
463 | |||
464 | /** |
||
465 | * Selects the like(s) for a database query. |
||
466 | * |
||
467 | * @param string|array field name or array of field => match pairs |
||
468 | * @param string like value to match with field |
||
469 | * @param boolean automatically add starting and ending wildcards |
||
470 | * @return Database_Core This Database object. |
||
471 | */ |
||
472 | View Code Duplication | public function like($field, $match = '', $auto = true) |
|
483 | |||
484 | /** |
||
485 | * Selects the or like(s) for a database query. |
||
486 | * |
||
487 | * @param string|array field name or array of field => match pairs |
||
488 | * @param string like value to match with field |
||
489 | * @param boolean automatically add starting and ending wildcards |
||
490 | * @return Database_Core This Database object. |
||
491 | */ |
||
492 | View Code Duplication | public function orlike($field, $match = '', $auto = true) |
|
503 | |||
504 | /** |
||
505 | * Selects the not like(s) for a database query. |
||
506 | * |
||
507 | * @param string|array field name or array of field => match pairs |
||
508 | * @param string like value to match with field |
||
509 | * @param boolean automatically add starting and ending wildcards |
||
510 | * @return Database_Core This Database object. |
||
511 | */ |
||
512 | View Code Duplication | public function notlike($field, $match = '', $auto = true) |
|
523 | |||
524 | /** |
||
525 | * Selects the or not like(s) for a database query. |
||
526 | * |
||
527 | * @param string|array field name or array of field => match pairs |
||
528 | * @param string like value to match with field |
||
529 | * @return Database_Core This Database object. |
||
530 | */ |
||
531 | View Code Duplication | public function ornotlike($field, $match = '', $auto = true) |
|
542 | |||
543 | /** |
||
544 | * Selects the like(s) for a database query. |
||
545 | * |
||
546 | * @param string|array field name or array of field => match pairs |
||
547 | * @param string like value to match with field |
||
548 | * @return Database_Core This Database object. |
||
549 | */ |
||
550 | View Code Duplication | public function regex($field, $match = '') |
|
561 | |||
562 | /** |
||
563 | * Selects the or like(s) for a database query. |
||
564 | * |
||
565 | * @param string|array field name or array of field => match pairs |
||
566 | * @param string like value to match with field |
||
567 | * @return Database_Core This Database object. |
||
568 | */ |
||
569 | View Code Duplication | public function orregex($field, $match = '') |
|
580 | |||
581 | /** |
||
582 | * Selects the not regex(s) for a database query. |
||
583 | * |
||
584 | * @param string|array field name or array of field => match pairs |
||
585 | * @param string regex value to match with field |
||
586 | * @return Database_Core This Database object. |
||
587 | */ |
||
588 | View Code Duplication | public function notregex($field, $match = '') |
|
599 | |||
600 | /** |
||
601 | * Selects the or not regex(s) for a database query. |
||
602 | * |
||
603 | * @param string|array field name or array of field => match pairs |
||
604 | * @param string regex value to match with field |
||
605 | * @return Database_Core This Database object. |
||
606 | */ |
||
607 | View Code Duplication | public function ornotregex($field, $match = '') |
|
618 | |||
619 | /** |
||
620 | * Chooses the column to group by in a select query. |
||
621 | * |
||
622 | * @param string column name to group by |
||
623 | * @return Database_Core This Database object. |
||
624 | */ |
||
625 | public function groupby($by) |
||
646 | |||
647 | /** |
||
648 | * Selects the having(s) for a database query. |
||
649 | * |
||
650 | * @param string|array key name or array of key => value pairs |
||
651 | * @param string value to match with key |
||
652 | * @param boolean disable quoting of WHERE clause |
||
653 | * @return Database_Core This Database object. |
||
654 | */ |
||
655 | public function having($key, $value = '', $quote = true) |
||
660 | |||
661 | /** |
||
662 | * Selects the or having(s) for a database query. |
||
663 | * |
||
664 | * @param string|array key name or array of key => value pairs |
||
665 | * @param string value to match with key |
||
666 | * @param boolean disable quoting of WHERE clause |
||
667 | * @return Database_Core This Database object. |
||
668 | */ |
||
669 | public function orhaving($key, $value = '', $quote = true) |
||
674 | |||
675 | /** |
||
676 | * Chooses which column(s) to order the select query by. |
||
677 | * |
||
678 | * @param string|array column(s) to order on, can be an array, single column, or comma seperated list of columns |
||
679 | * @param string direction of the order |
||
680 | * @return Database_Core This Database object. |
||
681 | */ |
||
682 | public function orderby($orderby, $direction = null) |
||
706 | |||
707 | /** |
||
708 | * Selects the limit section of a query. |
||
709 | * |
||
710 | * @param integer number of rows to limit result to |
||
711 | * @param integer offset in result to start returning rows from |
||
712 | * @return Database_Core This Database object. |
||
713 | */ |
||
714 | public function limit($limit, $offset = null) |
||
724 | |||
725 | /** |
||
726 | * Sets the offset portion of a query. |
||
727 | * |
||
728 | * @param integer offset value |
||
729 | * @return Database_Core This Database object. |
||
730 | */ |
||
731 | public function offset($value) |
||
737 | |||
738 | /** |
||
739 | * Allows key/value pairs to be set for inserting or updating. |
||
740 | * |
||
741 | * @param string|array key name or array of key => value pairs |
||
742 | * @param string value to match with key |
||
743 | * @return Database_Core This Database object. |
||
744 | */ |
||
745 | public function set($key, $value = '') |
||
762 | |||
763 | /** |
||
764 | * Compiles the select statement based on the other functions called and runs the query. |
||
765 | * |
||
766 | * @param string table name |
||
767 | * @param string limit clause |
||
768 | * @param string offset clause |
||
769 | * @return Database_Result |
||
770 | */ |
||
771 | public function get($table = '', $limit = null, $offset = null) |
||
791 | |||
792 | /** |
||
793 | * Compiles the select statement based on the other functions called and runs the query. |
||
794 | * |
||
795 | * @param string table name |
||
796 | * @param array where clause |
||
797 | * @param string limit clause |
||
798 | * @param string offset clause |
||
799 | * @return Database_Result This Database object. |
||
800 | */ |
||
801 | public function getwhere($table = '', $where = null, $limit = null, $offset = null) |
||
823 | |||
824 | /** |
||
825 | * Compiles the select statement based on the other functions called and returns the query string. |
||
826 | * |
||
827 | * @param string table name |
||
828 | * @param string limit clause |
||
829 | * @param string offset clause |
||
830 | * @return string sql string |
||
831 | */ |
||
832 | public function compile($table = '', $limit = null, $offset = null) |
||
848 | |||
849 | /** |
||
850 | * Compiles an insert string and runs the query. |
||
851 | * |
||
852 | * @param string table name |
||
853 | * @param array array of key/value pairs to insert |
||
854 | * @return Database_Result Query result |
||
855 | */ |
||
856 | public function insert($table = '', $set = null) |
||
883 | |||
884 | /** |
||
885 | * Adds an "IN" condition to the where clause |
||
886 | * |
||
887 | * @param string Name of the column being examined |
||
888 | * @param mixed An array or string to match against |
||
889 | * @param bool Generate a NOT IN clause instead |
||
890 | * @return Database_Core This Database object. |
||
891 | */ |
||
892 | public function in($field, $values, $not = false) |
||
911 | |||
912 | /** |
||
913 | * Adds a "NOT IN" condition to the where clause |
||
914 | * |
||
915 | * @param string Name of the column being examined |
||
916 | * @param mixed An array or string to match against |
||
917 | * @return Database_Core This Database object. |
||
918 | */ |
||
919 | public function notin($field, $values) |
||
923 | |||
924 | /** |
||
925 | * Compiles a merge string and runs the query. |
||
926 | * |
||
927 | * @param string table name |
||
928 | * @param array array of key/value pairs to merge |
||
929 | * @return Database_Result Query result |
||
930 | */ |
||
931 | View Code Duplication | public function merge($table = '', $set = null) |
|
954 | |||
955 | /** |
||
956 | * Compiles an update string and runs the query. |
||
957 | * |
||
958 | * @param string table name |
||
959 | * @param array associative array of update values |
||
960 | * @param array where clause |
||
961 | * @return Database_Result Query result |
||
962 | */ |
||
963 | View Code Duplication | public function update($table = '', $set = null, $where = null) |
|
990 | |||
991 | /** |
||
992 | * Compiles a delete string and runs the query. |
||
993 | * |
||
994 | * @param string table name |
||
995 | * @param array where clause |
||
996 | * @return Database_Result Query result |
||
997 | */ |
||
998 | public function delete($table = '', $where = null) |
||
1023 | |||
1024 | /** |
||
1025 | * Returns the last query run. |
||
1026 | * |
||
1027 | * @return string SQL |
||
1028 | */ |
||
1029 | public function last_query() |
||
1033 | |||
1034 | /** |
||
1035 | * Count query records. |
||
1036 | * |
||
1037 | * @param string table name |
||
1038 | * @param array where clause |
||
1039 | * @return integer |
||
1040 | */ |
||
1041 | public function count_records($table = false, $where = null) |
||
1059 | |||
1060 | /** |
||
1061 | * Resets all private select variables. |
||
1062 | * |
||
1063 | * @return void |
||
1064 | */ |
||
1065 | protected function reset_select() |
||
1078 | |||
1079 | /** |
||
1080 | * Resets all private insert and update variables. |
||
1081 | * |
||
1082 | * @return void |
||
1083 | */ |
||
1084 | protected function reset_write() |
||
1090 | |||
1091 | /** |
||
1092 | * Lists all the tables in the current database. |
||
1093 | * |
||
1094 | * @return array |
||
1095 | */ |
||
1096 | public function list_tables() |
||
1102 | |||
1103 | /** |
||
1104 | * See if a table exists in the database. |
||
1105 | * |
||
1106 | * @param string table name |
||
1107 | * @param boolean True to attach table prefix |
||
1108 | * @return boolean |
||
1109 | */ |
||
1110 | public function table_exists($table_name, $prefix = true) |
||
1118 | |||
1119 | /** |
||
1120 | * Combine a SQL statement with the bind values. Used for safe queries. |
||
1121 | * |
||
1122 | * @param string query to bind to the values |
||
1123 | * @param array array of values to bind to the query |
||
1124 | * @param string $sql |
||
1125 | * @return string |
||
1126 | */ |
||
1127 | public function compile_binds($sql, $binds) |
||
1148 | |||
1149 | /** |
||
1150 | * Get the field data for a database table, along with the field's attributes. |
||
1151 | * |
||
1152 | * @param string table name |
||
1153 | * @return array |
||
1154 | */ |
||
1155 | public function field_data($table = '') |
||
1161 | |||
1162 | /** |
||
1163 | * Get the field data for a database table, along with the field's attributes. |
||
1164 | * |
||
1165 | * @param string table name |
||
1166 | * @return array |
||
1167 | */ |
||
1168 | public function list_fields($table = '') |
||
1174 | |||
1175 | /** |
||
1176 | * Escapes a value for a query. |
||
1177 | * |
||
1178 | * @param mixed value to escape |
||
1179 | * @return string |
||
1180 | */ |
||
1181 | public function escape($value) |
||
1185 | |||
1186 | /** |
||
1187 | * Escapes a string for a query. |
||
1188 | * |
||
1189 | * @param string string to escape |
||
1190 | * @return string |
||
1191 | */ |
||
1192 | public function escape_str($str) |
||
1196 | |||
1197 | /** |
||
1198 | * Escapes a table name for a query. |
||
1199 | * |
||
1200 | * @param string string to escape |
||
1201 | * @param string $table |
||
1202 | * @return string |
||
1203 | */ |
||
1204 | public function escape_table($table) |
||
1208 | |||
1209 | /** |
||
1210 | * Escapes a column name for a query. |
||
1211 | * |
||
1212 | * @param string string to escape |
||
1213 | * @param string $table |
||
1214 | * @return string |
||
1215 | */ |
||
1216 | public function escape_column($table) |
||
1220 | |||
1221 | /** |
||
1222 | * Returns table prefix of current configuration. |
||
1223 | * |
||
1224 | * @return string |
||
1225 | */ |
||
1226 | public function table_prefix() |
||
1230 | |||
1231 | /** |
||
1232 | * Clears the query cache. |
||
1233 | * |
||
1234 | * @param string|TRUE clear cache by SQL statement or TRUE for last query |
||
1235 | * @return Database_Core This Database object. |
||
1236 | */ |
||
1237 | public function clear_cache($sql = null) |
||
1249 | |||
1250 | /** |
||
1251 | * Pushes existing query space onto the query stack. Use push |
||
1252 | * and pop to prevent queries from clashing before they are |
||
1253 | * executed |
||
1254 | * |
||
1255 | * @return Database_Core This Databaes object |
||
1256 | */ |
||
1257 | public function push() |
||
1277 | |||
1278 | /** |
||
1279 | * Pops from query stack into the current query space. |
||
1280 | * |
||
1281 | * @return Database_Core This Databaes object |
||
1282 | */ |
||
1283 | public function pop() |
||
1306 | |||
1307 | /** |
||
1308 | * Count the number of records in the last query, without LIMIT or OFFSET applied. |
||
1309 | * |
||
1310 | * @return integer |
||
1311 | */ |
||
1312 | public function count_last_query() |
||
1337 | } // End Database Class |
||
1338 | |||
1347 |
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.