dbhandler.init.php 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. <?php
  2. if (!defined('IS_INITPHP')) exit('Access Denied!');
  3. /*********************************************************************************
  4. * InitPHP 3.8.1 国产PHP开发框架 Dao-ddb 多库-主从-分表解决方案
  5. *-------------------------------------------------------------------------------
  6. * 版权所有: CopyRight By initphp.com
  7. * 您可以自由使用该源码,但是在使用过程中,请保留作者信息。尊重他人劳动成果就是尊重自己
  8. *-------------------------------------------------------------------------------
  9. * $Author:zhuli
  10. * $Dtime:2013-5-29
  11. ***********************************************************************************/
  12. require_once("driver/dbbase.init.php");
  13. class dbhandlerInit {
  14. protected static $dbArr = array(); // 存储 driver,db对象
  15. protected $db = NULL; //DB引擎对象
  16. protected $driverArr = array();
  17. protected $dbModel = NULL; //DB配置模型,默认为default
  18. /**
  19. * 数据库初始化,DB切换入口
  20. * 1. 可以在使用中通过$this->init_db('test')来切换数据库
  21. * 2. 该函数是DB默认初始化入口
  22. * 3. 支持多数据库链接,主从,随机分布式数据库
  23. * @param obj $db
  24. */
  25. public function init_db($db = '') {
  26. $InitPHP_conf = InitPHP::getConfig();
  27. $this->dbModel = ($db == '') ? 'default' : $db; //Db模型
  28. $driver = $InitPHP_conf['db']['driver']; //Db引擎
  29. if (isset(self::$dbArr[$this->dbModel])) {
  30. return true;
  31. }
  32. if (!isset($InitPHP_conf['db'][$this->dbModel])) {
  33. InitPHP::initError('database confing model {'.$this->dbModel.'} is error!');
  34. }
  35. $db_type = $InitPHP_conf['db'][$this->dbModel]['db_type'];
  36. $config = $InitPHP_conf['db'][$this->dbModel];
  37. switch ($db_type) {
  38. case 1: //主从模型
  39. $key = floor(mt_rand(1,(count($config) - 2)));
  40. self::$dbArr[$this->dbModel]['master']['link_id'] = $this->db_connect($config[0], $driver);
  41. self::$dbArr[$this->dbModel]['salver']['link_id'] = $this->db_connect($config[$key], $driver);
  42. break;
  43. case 2: //随机模型
  44. $key = floor(mt_rand(0,count($config) - 2));
  45. self::$dbArr[$this->dbModel]['link_id'] = $this->db_connect($config[$key], $driver);
  46. break;
  47. default: //默认单机模型
  48. self::$dbArr[$this->dbModel]['link_id'] = $this->db_connect($config[0], $driver);
  49. break;
  50. }
  51. return true;
  52. }
  53. /**
  54. * 获取link_id 数据库链接资源符
  55. * @param string $sql SQL语句进行分析
  56. * @return object
  57. */
  58. protected function get_link_id($sql) {
  59. $InitPHP_conf = InitPHP::getConfig();
  60. $db_type = $InitPHP_conf['db'][$this->dbModel]['db_type'];
  61. if (isset($InitPHP_conf['issqlcontrol']) && $InitPHP_conf['issqlcontrol'] == 1) {
  62. $InitPHP_conf['sqlcontrolarr'][] = $sql;
  63. InitPHP::setConfig('sqlcontrolarr', $InitPHP_conf['sqlcontrolarr']);
  64. }
  65. if ($db_type == 1) { //主从
  66. if ($this->is_insert($sql)) {
  67. $this->db->link_id = self::$dbArr[$this->dbModel]['master']['link_id'];
  68. } else {
  69. $this->db->link_id = self::$dbArr[$this->dbModel]['salver']['link_id'];
  70. }
  71. } else {
  72. $this->db->link_id = self::$dbArr[$this->dbModel]['link_id'];
  73. }
  74. return $this->db->link_id;
  75. }
  76. /**
  77. * 每次query执行完毕后,都会将默认的link_id指向默认数据库链接地址
  78. * @return object
  79. */
  80. protected function set_default_link_id() {
  81. if (isset(self::$dbArr['default'])) {
  82. $this->dbModel = 'default';
  83. $this->db->link_id = self::$dbArr[$this->dbModel]['link_id'];
  84. return true;
  85. }
  86. return false;
  87. }
  88. /**
  89. * DB链接器,主要用来链接数据库
  90. * 1. config 必要的参数:host、username、password、
  91. * database、charset、pconnect
  92. * 2. dirver 默认如果是mysql连接,可以不填写,如果填写了driver,则会使用不同的数据库类型,例如:mysqli
  93. * 3. $this->db 是db类对象,单例
  94. * @param array $config
  95. * @return object
  96. */
  97. private function db_connect($config, $driver) {
  98. $host = $config['host'];
  99. $user = $config['username'];
  100. $password = $config['password'];
  101. $database = $config['database'];
  102. $charset = $config['charset'];
  103. $pconnect = $config['pconnect'];
  104. $driver = (!isset($driver)) ? 'mysql' : $driver;
  105. if ($this->db == NULL) {
  106. $this->db = $this->get_db_driver($driver); //DB对象
  107. }
  108. return $this->db->connect($host, $user, $password, $database, $charset, $pconnect);
  109. }
  110. /**
  111. * 获取数组引擎对象
  112. * @param string $driver 暂时只支持mysql
  113. * @return object
  114. */
  115. private function get_db_driver($driver) {
  116. $file = $driver . '.init.php';
  117. $class = $driver . 'Init';
  118. require(INITPHP_PATH . '/core/dao/db/driver/' . $file);
  119. return InitPHP::loadclass($class);
  120. }
  121. /**
  122. * SQL分析器
  123. * @param string $sql SQL语句
  124. * @return bool
  125. */
  126. private function is_insert($sql) {
  127. $sql = trim($sql);
  128. $sql_temp = strtoupper(substr($sql, 0, 6));
  129. if ($sql_temp == 'SELECT') return false;
  130. return true;
  131. }
  132. /**
  133. * 按月分表-分库方法
  134. * 1. 当数据表数据量过大的时候,可以根据按月分表的方法来进行分表
  135. * 2. 按月分库会根据当前的时间来决定是几月份的数据
  136. * 3. 按月分库$defaultId,可以自定义填入月份,例如:get_mon_table('test', 2),则返回 test_02
  137. * Dao中使用方法:$this->dao->db->month_identify($tbl, $defaultId = '')
  138. * @param string $tbl
  139. * @param string $defaultId
  140. */
  141. public function month_identify($tbl, $defaultId = '') {
  142. if (empty ( $defaultId )) {
  143. $mon = sprintf ( '%02d', date ( 'm', InitPHP::getTime() ));
  144. return $tbl . '_' . $mon;
  145. } else {
  146. return $tbl . '_' . sprintf ( '%02d', $defaultId );
  147. }
  148. }
  149. /**
  150. * 根据数值来确定分表-分库方法
  151. * 1. 可以自定义分表-分库的模板前缀$tbl变量
  152. * 2. 可以自定义截取长度
  153. * 3. 一般可以根据用户UID来获取分表或者分库
  154. * Dao中使用方法:$this->dao->db->num_identify($num, $tbl, $default = 1)
  155. * @param int $num 数值
  156. * @param string $tbl 模板前缀
  157. * @param int $default 默认截取长度
  158. */
  159. public function num_identify($num, $tbl, $default = 1) {
  160. $num = (string) $num;
  161. $len = strlen($num);
  162. if ($len >= $default)
  163. $str = substr($num, $len - $default, $default);
  164. else
  165. $str = str_pad($num, $default, '0', STR_PAD_LEFT);
  166. return $tbl . '_' . $str;
  167. }
  168. /**
  169. * 求余数的方式获取分表-分库方法
  170. * 1. 求余方式余数比较少,适合小型的分表法
  171. * 2. 可以自定义求余除数
  172. * Dao中使用方法:$this->dao->db->fmod_identify($num, $tbl, $default = 7)
  173. * @param int $num
  174. * @param string $tbl
  175. * @param int $default
  176. * @return
  177. */
  178. public function fmod_identify($num, $tbl, $default = 7) {
  179. return $tbl . '_' . fmod($num/$default);
  180. }
  181. }