Connection.php 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | ThinkPHP [ WE CAN DO IT JUST THINK ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2006~2019 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. declare(strict_types=1);
  12. namespace think\db;
  13. use Psr\SimpleCache\CacheInterface;
  14. use think\DbManager;
  15. /**
  16. * 数据库连接基础类
  17. */
  18. abstract class Connection implements ConnectionInterface
  19. {
  20. /**
  21. * 当前SQL指令
  22. * @var string
  23. */
  24. protected $queryStr = '';
  25. /**
  26. * 返回或者影响记录数
  27. * @var int
  28. */
  29. protected $numRows = 0;
  30. /**
  31. * 事务指令数
  32. * @var int
  33. */
  34. protected $transTimes = 0;
  35. /**
  36. * 错误信息
  37. * @var string
  38. */
  39. protected $error = '';
  40. /**
  41. * 数据库连接ID 支持多个连接
  42. * @var array
  43. */
  44. protected $links = [];
  45. /**
  46. * 当前连接ID
  47. * @var object
  48. */
  49. protected $linkID;
  50. /**
  51. * 当前读连接ID
  52. * @var object
  53. */
  54. protected $linkRead;
  55. /**
  56. * 当前写连接ID
  57. * @var object
  58. */
  59. protected $linkWrite;
  60. /**
  61. * 数据表信息
  62. * @var array
  63. */
  64. protected $info = [];
  65. /**
  66. * 查询开始时间
  67. * @var float
  68. */
  69. protected $queryStartTime;
  70. /**
  71. * Builder对象
  72. * @var Builder
  73. */
  74. protected $builder;
  75. /**
  76. * Db对象
  77. * @var DbManager
  78. */
  79. protected $db;
  80. /**
  81. * 是否读取主库
  82. * @var bool
  83. */
  84. protected $readMaster = false;
  85. /**
  86. * 数据库连接参数配置
  87. * @var array
  88. */
  89. protected $config = [];
  90. /**
  91. * 缓存对象
  92. * @var CacheInterface
  93. */
  94. protected $cache;
  95. /**
  96. * 架构函数 读取数据库配置信息
  97. * @access public
  98. * @param array $config 数据库配置数组
  99. */
  100. public function __construct(array $config = [])
  101. {
  102. if (!empty($config)) {
  103. $this->config = array_merge($this->config, $config);
  104. }
  105. // 创建Builder对象
  106. $class = $this->getBuilderClass();
  107. $this->builder = new $class($this);
  108. }
  109. /**
  110. * 获取当前的builder实例对象
  111. * @access public
  112. * @return Builder
  113. */
  114. public function getBuilder()
  115. {
  116. return $this->builder;
  117. }
  118. /**
  119. * 创建查询对象
  120. */
  121. public function newQuery()
  122. {
  123. $class = $this->getQueryClass();
  124. /** @var BaseQuery $query */
  125. $query = new $class($this);
  126. $timeRule = $this->db->getConfig('time_query_rule');
  127. if (!empty($timeRule)) {
  128. $query->timeRule($timeRule);
  129. }
  130. return $query;
  131. }
  132. /**
  133. * 指定表名开始查询
  134. * @param $table
  135. * @return BaseQuery
  136. */
  137. public function table($table)
  138. {
  139. return $this->newQuery()->table($table);
  140. }
  141. /**
  142. * 指定表名开始查询(不带前缀)
  143. * @param $name
  144. * @return BaseQuery
  145. */
  146. public function name($name)
  147. {
  148. return $this->newQuery()->name($name);
  149. }
  150. /**
  151. * 设置当前的数据库Db对象
  152. * @access public
  153. * @param DbManager $db
  154. * @return void
  155. */
  156. public function setDb(DbManager $db)
  157. {
  158. $this->db = $db;
  159. }
  160. /**
  161. * 设置当前的缓存对象
  162. * @access public
  163. * @param CacheInterface $cache
  164. * @return void
  165. */
  166. public function setCache(CacheInterface $cache)
  167. {
  168. $this->cache = $cache;
  169. }
  170. /**
  171. * 获取当前的缓存对象
  172. * @access public
  173. * @return CacheInterface|null
  174. */
  175. public function getCache()
  176. {
  177. return $this->cache;
  178. }
  179. /**
  180. * 获取数据库的配置参数
  181. * @access public
  182. * @param string $config 配置名称
  183. * @return mixed
  184. */
  185. public function getConfig(string $config = '')
  186. {
  187. if ('' === $config) {
  188. return $this->config;
  189. }
  190. return $this->config[$config] ?? null;
  191. }
  192. /**
  193. * 数据库SQL监控
  194. * @access protected
  195. * @param string $sql 执行的SQL语句 留空自动获取
  196. * @param bool $master 主从标记
  197. * @return void
  198. */
  199. protected function trigger(string $sql = '', bool $master = false): void
  200. {
  201. $listen = $this->db->getListen();
  202. if (empty($listen)) {
  203. $listen[] = function ($sql, $time, $master) {
  204. if (0 === strpos($sql, 'CONNECT:')) {
  205. $this->db->log($sql);
  206. return;
  207. }
  208. // 记录SQL
  209. if (is_bool($master)) {
  210. // 分布式记录当前操作的主从
  211. $master = $master ? 'master|' : 'slave|';
  212. } else {
  213. $master = '';
  214. }
  215. $this->db->log($sql . ' [ ' . $master . 'RunTime:' . $time . 's ]');
  216. };
  217. }
  218. $runtime = number_format((microtime(true) - $this->queryStartTime), 6);
  219. $sql = $sql ?: $this->getLastsql();
  220. if (empty($this->config['deploy'])) {
  221. $master = null;
  222. }
  223. foreach ($listen as $callback) {
  224. if (is_callable($callback)) {
  225. $callback($sql, $runtime, $master);
  226. }
  227. }
  228. }
  229. /**
  230. * 缓存数据
  231. * @access protected
  232. * @param CacheItem $cacheItem 缓存Item
  233. */
  234. protected function cacheData(CacheItem $cacheItem)
  235. {
  236. if ($cacheItem->getTag() && method_exists($this->cache, 'tag')) {
  237. $this->cache->tag($cacheItem->getTag())->set($cacheItem->getKey(), $cacheItem->get(), $cacheItem->getExpire());
  238. } else {
  239. $this->cache->set($cacheItem->getKey(), $cacheItem->get(), $cacheItem->getExpire());
  240. }
  241. }
  242. /**
  243. * 分析缓存Key
  244. * @access protected
  245. * @param BaseQuery $query 查询对象
  246. * @param string $method 查询方法
  247. * @return string
  248. */
  249. protected function getCacheKey(BaseQuery $query, string $method = ''): string
  250. {
  251. if (!empty($query->getOptions('key')) && empty($method)) {
  252. $key = 'think_' . $this->getConfig('database') . '.' . $query->getTable() . '|' . $query->getOptions('key');
  253. } else {
  254. $key = $query->getQueryGuid();
  255. }
  256. return $key;
  257. }
  258. /**
  259. * 分析缓存
  260. * @access protected
  261. * @param BaseQuery $query 查询对象
  262. * @param array $cache 缓存信息
  263. * @param string $method 查询方法
  264. * @return CacheItem
  265. */
  266. protected function parseCache(BaseQuery $query, array $cache, string $method = ''): CacheItem
  267. {
  268. [$key, $expire, $tag] = $cache;
  269. if ($key instanceof CacheItem) {
  270. $cacheItem = $key;
  271. } else {
  272. if (true === $key) {
  273. $key = $this->getCacheKey($query, $method);
  274. }
  275. $cacheItem = new CacheItem($key);
  276. $cacheItem->expire($expire);
  277. $cacheItem->tag($tag);
  278. }
  279. return $cacheItem;
  280. }
  281. /**
  282. * 获取返回或者影响的记录数
  283. * @access public
  284. * @return integer
  285. */
  286. public function getNumRows(): int
  287. {
  288. return $this->numRows;
  289. }
  290. /**
  291. * 析构方法
  292. * @access public
  293. */
  294. public function __destruct()
  295. {
  296. // 关闭连接
  297. $this->close();
  298. }
  299. }