Db.class.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +----------------------------------------------------------------------
  9. // | Author: liu21st <liu21st@gmail.com>
  10. // +----------------------------------------------------------------------
  11. namespace Think;
  12. /**
  13. * ThinkPHP 数据库中间层实现类
  14. */
  15. class Db
  16. {
  17. private static $instance = array(); // 数据库连接实例
  18. private static $_instance = null; // 当前数据库连接实例
  19. /**
  20. * 取得数据库类实例
  21. * @static
  22. * @access public
  23. * @param mixed $config 连接配置
  24. * @return Object 返回数据库驱动类
  25. */
  26. public static function getInstance($config = array())
  27. {
  28. $md5 = md5(serialize($config));
  29. if (!isset(self::$instance[$md5])) {
  30. // 解析连接参数 支持数组和字符串
  31. $options = self::parseConfig($config);
  32. // 兼容mysqli
  33. if ('mysqli' == $options['type']) {
  34. $options['type'] = 'mysql';
  35. }
  36. // 如果采用lite方式 仅支持原生SQL 包括query和execute方法
  37. $class = !empty($options['lite']) ? 'Think\Db\Lite' : 'Think\\Db\\Driver\\' . ucwords(strtolower($options['type']));
  38. if (class_exists($class)) {
  39. self::$instance[$md5] = new $class($options);
  40. } else {
  41. // 类没有定义
  42. E(L('_NO_DB_DRIVER_') . ': ' . $class);
  43. }
  44. }
  45. self::$_instance = self::$instance[$md5];
  46. return self::$_instance;
  47. }
  48. /**
  49. * 数据库连接参数解析
  50. * @static
  51. * @access private
  52. * @param mixed $config
  53. * @return array
  54. */
  55. private static function parseConfig($config)
  56. {
  57. if (!empty($config)) {
  58. if (is_string($config)) {
  59. return self::parseDsn($config);
  60. }
  61. $config = array_change_key_case($config);
  62. $config = array(
  63. 'type' => $config['db_type'],
  64. 'username' => $config['db_user'],
  65. 'password' => $config['db_pwd'],
  66. 'hostname' => $config['db_host'],
  67. 'hostport' => $config['db_port'],
  68. 'database' => $config['db_name'],
  69. 'dsn' => isset($config['db_dsn']) ? $config['db_dsn'] : null,
  70. 'params' => isset($config['db_params']) ? $config['db_params'] : null,
  71. 'charset' => isset($config['db_charset']) ? $config['db_charset'] : 'utf8',
  72. 'deploy' => isset($config['db_deploy_type']) ? $config['db_deploy_type'] : 0,
  73. 'rw_separate' => isset($config['db_rw_separate']) ? $config['db_rw_separate'] : false,
  74. 'master_num' => isset($config['db_master_num']) ? $config['db_master_num'] : 1,
  75. 'slave_no' => isset($config['db_slave_no']) ? $config['db_slave_no'] : '',
  76. 'debug' => isset($config['db_debug']) ? $config['db_debug'] : APP_DEBUG,
  77. 'lite' => isset($config['db_lite']) ? $config['db_lite'] : false,
  78. );
  79. } else {
  80. $config = array(
  81. 'type' => C('DB_TYPE'),
  82. 'username' => C('DB_USER'),
  83. 'password' => C('DB_PWD'),
  84. 'hostname' => C('DB_HOST'),
  85. 'hostport' => C('DB_PORT'),
  86. 'database' => C('DB_NAME'),
  87. 'dsn' => C('DB_DSN'),
  88. 'params' => C('DB_PARAMS'),
  89. 'charset' => C('DB_CHARSET'),
  90. 'deploy' => C('DB_DEPLOY_TYPE'),
  91. 'rw_separate' => C('DB_RW_SEPARATE'),
  92. 'master_num' => C('DB_MASTER_NUM'),
  93. 'slave_no' => C('DB_SLAVE_NO'),
  94. 'debug' => C('DB_DEBUG', null, APP_DEBUG),
  95. 'lite' => C('DB_LITE'),
  96. );
  97. }
  98. return $config;
  99. }
  100. /**
  101. * DSN解析
  102. * 格式: mysql://username:passwd@localhost:3306/DbName?param1=val1&param2=val2#utf8
  103. * @static
  104. * @access private
  105. * @param string $dsnStr
  106. * @return array
  107. */
  108. private static function parseDsn($dsnStr)
  109. {
  110. if (empty($dsnStr)) {return false;}
  111. $info = parse_url($dsnStr);
  112. if (!$info) {
  113. return false;
  114. }
  115. $dsn = array(
  116. 'type' => $info['scheme'],
  117. 'username' => isset($info['user']) ? $info['user'] : '',
  118. 'password' => isset($info['pass']) ? $info['pass'] : '',
  119. 'hostname' => isset($info['host']) ? $info['host'] : '',
  120. 'hostport' => isset($info['port']) ? $info['port'] : '',
  121. 'database' => isset($info['path']) ? ltrim($info['path'], '/') : '',
  122. 'charset' => isset($info['fragment']) ? $info['fragment'] : 'utf8',
  123. );
  124. if (isset($info['query'])) {
  125. parse_str($info['query'], $dsn['params']);
  126. } else {
  127. $dsn['params'] = array();
  128. }
  129. return $dsn;
  130. }
  131. // 调用驱动类的方法
  132. public static function __callStatic($method, $params)
  133. {
  134. return call_user_func_array(array(self::$_instance, $method), $params);
  135. }
  136. }