PageRenderTime 64ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/var/Typecho/Db.php

https://gitlab.com/wuhang2003/typecho
PHP | 440 lines | 174 code | 58 blank | 208 comment | 20 complexity | 995e643d784545ff45022502b3bccc80 MD5 | raw file
  1. <?php
  2. /**
  3. * Typecho Blog Platform
  4. *
  5. * @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
  6. * @license GNU General Public License 2.0
  7. * @version $Id: Db.php 107 2008-04-11 07:14:43Z magike.net $
  8. */
  9. /**
  10. * 包含获取数据支持方法的类.
  11. * 必须定义__TYPECHO_DB_HOST__, __TYPECHO_DB_PORT__, __TYPECHO_DB_NAME__,
  12. * __TYPECHO_DB_USER__, __TYPECHO_DB_PASS__, __TYPECHO_DB_CHAR__
  13. *
  14. * @package Db
  15. */
  16. class Typecho_Db
  17. {
  18. /** 读取数据库 */
  19. const READ = 1;
  20. /** 写入数据库 */
  21. const WRITE = 2;
  22. /** 升序方式 */
  23. const SORT_ASC = 'ASC';
  24. /** 降序方式 */
  25. const SORT_DESC = 'DESC';
  26. /** 表内连接方式 */
  27. const INNER_JOIN = 'INNER';
  28. /** 表外连接方式 */
  29. const OUTER_JOIN = 'OUTER';
  30. /** 表左连接方式 */
  31. const LEFT_JOIN = 'LEFT';
  32. /** 表右连接方式 */
  33. const RIGHT_JOIN = 'RIGHT';
  34. /** 数据库查询操作 */
  35. const SELECT = 'SELECT';
  36. /** 数据库更新操作 */
  37. const UPDATE = 'UPDATE';
  38. /** 数据库插入操作 */
  39. const INSERT = 'INSERT';
  40. /** 数据库删除操作 */
  41. const DELETE = 'DELETE';
  42. /**
  43. * 数据库适配器
  44. * @var Typecho_Db_Adapter
  45. */
  46. private $_adapter;
  47. /**
  48. * 默认配置
  49. *
  50. * @access private
  51. * @var Typecho_Config
  52. */
  53. private $_config;
  54. /**
  55. * 连接池
  56. *
  57. * @access private
  58. * @var array
  59. */
  60. private $_pool;
  61. /**
  62. * 已经连接
  63. *
  64. * @access private
  65. * @var array
  66. */
  67. private $_connectedPool;
  68. /**
  69. * 前缀
  70. *
  71. * @access private
  72. * @var string
  73. */
  74. private $_prefix;
  75. /**
  76. * 适配器名称
  77. *
  78. * @access private
  79. * @var string
  80. */
  81. private $_adapterName;
  82. /**
  83. * 实例化的数据库对象
  84. * @var Typecho_Db
  85. */
  86. private static $_instance;
  87. /**
  88. * 数据库类构造函数
  89. *
  90. * @param mixed $adapterName 适配器名称
  91. * @param string $prefix 前缀
  92. * @throws Typecho_Db_Exception
  93. */
  94. public function __construct($adapterName, $prefix = 'typecho_')
  95. {
  96. /** 获取适配器名称 */
  97. $this->_adapterName = $adapterName;
  98. /** 数据库适配器 */
  99. $adapterName = 'Typecho_Db_Adapter_' . $adapterName;
  100. if (!call_user_func(array($adapterName, 'isAvailable'))) {
  101. throw new Typecho_Db_Exception("Adapter {$adapterName} is not available");
  102. }
  103. $this->_prefix = $prefix;
  104. /** 初始化内部变量 */
  105. $this->_pool = array();
  106. $this->_connectedPool = array();
  107. $this->_config = array();
  108. //实例化适配器对象
  109. $this->_adapter = new $adapterName();
  110. }
  111. /**
  112. * 获取适配器名称
  113. *
  114. * @access public
  115. * @return string
  116. */
  117. public function getAdapterName()
  118. {
  119. return $this->_adapterName;
  120. }
  121. /**
  122. * 获取表前缀
  123. *
  124. * @access public
  125. * @return string
  126. */
  127. public function getPrefix()
  128. {
  129. return $this->_prefix;
  130. }
  131. /**
  132. * getConfig
  133. *
  134. * @access public
  135. * @return void
  136. */
  137. public function getConfig()
  138. {
  139. return $this->_config;
  140. }
  141. /**
  142. * 重置连接池
  143. *
  144. * @return void
  145. */
  146. public function flushPool()
  147. {
  148. $this->_connectedPool = array();
  149. }
  150. /**
  151. * 选择数据库
  152. *
  153. * @param int $op
  154. * @return Typecho_Db_Adapter
  155. */
  156. public function selectDb($op)
  157. {
  158. if (!isset($this->_connectedPool[$op])) {
  159. if (empty($this->_pool[$op])) {
  160. /** Typecho_Db_Exception */
  161. throw new Typecho_Db_Exception('Missing Database Connection');
  162. }
  163. //获取相应读或写服务器连接池中的一个
  164. $selectConnection = rand(0, count($this->_pool[$op]) - 1);
  165. //获取随机获得的连接池配置
  166. $selectConnectionConfig = $this->_config[$this->_pool[$op][$selectConnection]];
  167. $selectConnectionHandle = $this->_adapter->connect($selectConnectionConfig);
  168. $this->_connectedPool[$op] = &$selectConnectionHandle;
  169. }
  170. return $this->_connectedPool[$op];
  171. }
  172. /**
  173. * 获取SQL词法构建器实例化对象
  174. *
  175. * @return Typecho_Db_Query
  176. */
  177. public function sql()
  178. {
  179. return new Typecho_Db_Query($this->_adapter, $this->_prefix);
  180. }
  181. /**
  182. * 为多数据库提供支持
  183. *
  184. * @access public
  185. * @param Typecho_Db $db 数据库实例
  186. * @param integer $op 数据库操作
  187. * @return void
  188. */
  189. public function addServer($config, $op)
  190. {
  191. $this->_config[] = Typecho_Config::factory($config);
  192. $key = count($this->_config) - 1;
  193. /** 将连接放入池中 */
  194. switch ($op) {
  195. case self::READ:
  196. case self::WRITE:
  197. $this->_pool[$op][] = $key;
  198. break;
  199. default:
  200. $this->_pool[self::READ][] = $key;
  201. $this->_pool[self::WRITE][] = $key;
  202. break;
  203. }
  204. }
  205. /**
  206. * 获取版本
  207. *
  208. * @param int $op
  209. * @return string
  210. */
  211. public function getVersion($op = self::READ)
  212. {
  213. return $this->_adapter->getVersion($this->selectDb($op));
  214. }
  215. /**
  216. * 设置默认数据库对象
  217. *
  218. * @access public
  219. * @param Typecho_Db $db 数据库对象
  220. * @return void
  221. */
  222. public static function set(Typecho_Db $db)
  223. {
  224. self::$_instance = $db;
  225. }
  226. /**
  227. * 获取数据库实例化对象
  228. * 用静态变量存储实例化的数据库对象,可以保证数据连接仅进行一次
  229. *
  230. * @return Typecho_Db
  231. * @throws Typecho_Db_Exception
  232. */
  233. public static function get()
  234. {
  235. if (empty(self::$_instance)) {
  236. /** Typecho_Db_Exception */
  237. throw new Typecho_Db_Exception('Missing Database Object');
  238. }
  239. return self::$_instance;
  240. }
  241. /**
  242. * 选择查询字段
  243. *
  244. * @access public
  245. * @param mixed $field 查询字段
  246. * @return Typecho_Db_Query
  247. */
  248. public function select()
  249. {
  250. $args = func_get_args();
  251. return call_user_func_array(array($this->sql(), 'select'), $args ? $args : array('*'));
  252. }
  253. /**
  254. * 更新记录操作(UPDATE)
  255. *
  256. * @param string $table 需要更新记录的表
  257. * @return Typecho_Db_Query
  258. */
  259. public function update($table)
  260. {
  261. return $this->sql()->update($table);
  262. }
  263. /**
  264. * 删除记录操作(DELETE)
  265. *
  266. * @param string $table 需要删除记录的表
  267. * @return Typecho_Db_Query
  268. */
  269. public function delete($table)
  270. {
  271. return $this->sql()->delete($table);
  272. }
  273. /**
  274. * 插入记录操作(INSERT)
  275. *
  276. * @param string $table 需要插入记录的表
  277. * @return Typecho_Db_Query
  278. */
  279. public function insert($table)
  280. {
  281. return $this->sql()->insert($table);
  282. }
  283. /**
  284. * 执行查询语句
  285. *
  286. * @param mixed $query 查询语句或者查询对象
  287. * @param boolean $op 数据库读写状态
  288. * @param string $action 操作动作
  289. * @return mixed
  290. */
  291. public function query($query, $op = self::READ, $action = self::SELECT)
  292. {
  293. /** 在适配器中执行查询 */
  294. if ($query instanceof Typecho_Db_Query) {
  295. $action = $query->getAttribute('action');
  296. $op = (self::UPDATE == $action || self::DELETE == $action
  297. || self::INSERT == $action) ? self::WRITE : self::READ;
  298. } else if (!is_string($query)) {
  299. /** 如果query不是对象也不是字符串,那么将其判断为查询资源句柄,直接返回 */
  300. return $query;
  301. }
  302. /** 选择连接池 */
  303. $handle = $this->selectDb($op);
  304. /** 提交查询 */
  305. $resource = $this->_adapter->query($query, $handle, $op, $action);
  306. if ($action) {
  307. //根据查询动作返回相应资源
  308. switch ($action) {
  309. case self::UPDATE:
  310. case self::DELETE:
  311. return $this->_adapter->affectedRows($resource, $handle);
  312. case self::INSERT:
  313. return $this->_adapter->lastInsertId($resource, $handle);
  314. case self::SELECT:
  315. default:
  316. return $resource;
  317. }
  318. } else {
  319. //如果直接执行查询语句则返回资源
  320. return $resource;
  321. }
  322. }
  323. /**
  324. * 一次取出所有行
  325. *
  326. * @param mixed $query 查询对象
  327. * @param array $filter 行过滤器函数,将查询的每一行作为第一个参数传入指定的过滤器中
  328. * @return array
  329. */
  330. public function fetchAll($query, array $filter = NULL)
  331. {
  332. //执行查询
  333. $resource = $this->query($query, self::READ);
  334. $result = array();
  335. /** 取出过滤器 */
  336. if (!empty($filter)) {
  337. list($object, $method) = $filter;
  338. }
  339. //取出每一行
  340. while ($rows = $this->_adapter->fetch($resource)) {
  341. //判断是否有过滤器
  342. $result[] = $filter ? call_user_func(array(&$object, $method), $rows) : $rows;
  343. }
  344. return $result;
  345. }
  346. /**
  347. * 一次取出一行
  348. *
  349. * @param mixed $query 查询对象
  350. * @param array $filter 行过滤器函数,将查询的每一行作为第一个参数传入指定的过滤器中
  351. * @return stdClass
  352. */
  353. public function fetchRow($query, array $filter = NULL)
  354. {
  355. $resource = $this->query($query, self::READ);
  356. /** 取出过滤器 */
  357. if ($filter) {
  358. list($object, $method) = $filter;
  359. }
  360. return ($rows = $this->_adapter->fetch($resource)) ?
  361. ($filter ? $object->$method($rows) : $rows) :
  362. array();
  363. }
  364. /**
  365. * 一次取出一个对象
  366. *
  367. * @param mixed $query 查询对象
  368. * @param array $filter 行过滤器函数,将查询的每一行作为第一个参数传入指定的过滤器中
  369. * @return array
  370. */
  371. public function fetchObject($query, array $filter = NULL)
  372. {
  373. $resource = $this->query($query, self::READ);
  374. /** 取出过滤器 */
  375. if ($filter) {
  376. list($object, $method) = $filter;
  377. }
  378. return ($rows = $this->_adapter->fetchObject($resource)) ?
  379. ($filter ? $object->$method($rows) : $rows) :
  380. new stdClass();
  381. }
  382. }