Sql.class.php 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  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\Session\Driver;
  12. use PDO;
  13. /**
  14. * 数据库方式Session驱动
  15. * CREATE TABLE think_session (
  16. * session_id varchar(255) NOT NULL,
  17. * session_expire int(11) NOT NULL,
  18. * session_data blob,
  19. * UNIQUE KEY `session_id` (`session_id`)
  20. * );.
  21. */
  22. class Sql
  23. {
  24. /**
  25. * Session有效时间.
  26. */
  27. protected $lifeTime = '';
  28. /**
  29. * session保存的数据库名.
  30. */
  31. protected $sessionTable = '';
  32. /**
  33. * 数据库句柄.
  34. */
  35. protected $hander = array();
  36. // PDO连接参数
  37. protected $options = array(PDO::ATTR_CASE => PDO::CASE_LOWER, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL, PDO::ATTR_STRINGIFY_FETCHES => false);
  38. /**
  39. * 解析pdo连接的dsn信息.
  40. *
  41. * @param unknown $name 数据库名称
  42. * @param unknown $host 数据库地址
  43. * @param unknown $port 端口
  44. * @param unknown $socket socket
  45. * @param unknown $charset 字符集
  46. *
  47. * @return string
  48. */
  49. protected function parseDsn($name, $host = '127.0.0.1', $port = '', $socket = '', $charset = '')
  50. {
  51. $dsn = 'mysql:dbname=' . $name . ';host=' . $host;
  52. if (!empty($port)) {
  53. $dsn .= ';port=' . $port;
  54. } elseif (!empty($socket)) {
  55. $dsn .= ';unix_socket=' . $socket;
  56. }
  57. if (!empty($charset)) {
  58. //为兼容各版本PHP,用两种方式设置编码
  59. $this->options[\PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES ' . $charset;
  60. $dsn .= ';charset=' . $charset;
  61. }
  62. return $dsn;
  63. }
  64. /**
  65. * 打开Session.
  66. *
  67. * @param string $savePath
  68. * @param mixed $sessName
  69. */
  70. public function open($savePath, $sessName)
  71. {
  72. $this->lifeTime = C('SESSION_EXPIRE') ? C('SESSION_EXPIRE') : ini_get('session.gc_maxlifetime');
  73. $this->sessionTable = C('SESSION_TABLE') ? C('SESSION_TABLE') : C('DB_PREFIX') . 'session';
  74. //分布式数据库
  75. $host = explode(',', C('DB_HOST'));
  76. $port = explode(',', C('DB_PORT'));
  77. $name = explode(',', C('DB_NAME'));
  78. $user = explode(',', C('DB_USER'));
  79. $pwd = explode(',', C('DB_PWD'));
  80. if (1 == C('DB_DEPLOY_TYPE')) {
  81. //读写分离
  82. if (C('DB_RW_SEPARATE')) {
  83. $w = floor(mt_rand(0, C('DB_MASTER_NUM') - 1));
  84. if (is_numeric(C('DB_SLAVE_NO'))) { //指定服务器读
  85. $r = C('DB_SLAVE_NO');
  86. } else {
  87. $r = floor(mt_rand(C('DB_MASTER_NUM'), count($host) - 1));
  88. }
  89. //主数据库链接
  90. $dsn = $this->parseDsn((isset($name[$w]) ? $name[$w] : $name[0]), $host[$w], (isset($port[$w]) ? $port[$w] : $port[0]));
  91. $hander = new PDO($dsn, (isset($user[$w]) ? $user[$w] : $user[0]), (isset($pwd[$w]) ? $pwd[$w] : $pwd[0]));
  92. if (!$hander) {
  93. return false;
  94. }
  95. $this->hander[0] = $hander;
  96. //从数据库链接
  97. $dsn = $this->parseDsn((isset($name[$r]) ? $name[$r] : $name[0]), $host[$r], (isset($port[$r]) ? $port[$r] : $port[0]));
  98. $hander = new PDO($dsn, (isset($user[$r]) ? $user[$r] : $user[0]), (isset($pwd[$r]) ? $pwd[$r] : $pwd[0]));
  99. if (!$hander) {
  100. return false;
  101. }
  102. $this->hander[1] = $hander;
  103. return true;
  104. }
  105. }
  106. //从数据库链接
  107. $r = floor(mt_rand(0, count($host) - 1));
  108. $dsn = $this->parseDsn((isset($name[$r]) ? $name[$r] : $name[0]), $host[$r], (isset($port[$r]) ? $port[$r] : $port[0]));
  109. $hander = new PDO($dsn, (isset($user[$r]) ? $user[$r] : $user[0]), (isset($pwd[$r]) ? $pwd[$r] : $pwd[0]));
  110. if (!$hander) {
  111. return false;
  112. }
  113. $this->hander = $hander;
  114. return true;
  115. }
  116. /**
  117. * 关闭Session.
  118. */
  119. public function close()
  120. {
  121. if (is_array($this->hander)) {
  122. $this->gc($this->lifeTime);
  123. return ($this->hander[0] = null) && ($this->hander[1] = null);
  124. }
  125. $this->gc($this->lifeTime);
  126. return $this->hander = null;
  127. }
  128. /**
  129. * 读取Session.
  130. *
  131. * @param string $sessID
  132. */
  133. public function read($sessID)
  134. {
  135. $hander = is_array($this->hander) ? $this->hander[1] : $this->hander;
  136. $res = $hander->prepare('SELECT session_data AS data FROM ' . $this->sessionTable . " WHERE session_id = '$sessID' AND session_expire >" . time());
  137. $res->execute();
  138. if ($result = $res->fetch(PDO::FETCH_ASSOC)) {
  139. return $result['data'];
  140. }
  141. return '';
  142. }
  143. /**
  144. * 写入Session.
  145. *
  146. * @param string $sessID
  147. * @param string $sessData
  148. */
  149. public function write($sessID, $sessData)
  150. {
  151. $hander = is_array($this->hander) ? $this->hander[0] : $this->hander;
  152. $expire = time() + $this->lifeTime;
  153. $sessData = addslashes($sessData);
  154. $res = $hander->prepare("SELECT COUNT(*) FROM " . $this->sessionTable . " WHERE `session_id` = '$sessID'");
  155. $res->execute();
  156. $result = $res->fetch(PDO::FETCH_ASSOC);
  157. if ($result['COUNT(*)'] === '1') {
  158. $res = $hander->exec('UPDATE ' . $this->sessionTable . " SET `session_data` = '$sessData', `session_expire` = '$expire', `update_time` = '" . time() . "' WHERE `session_id` = '$sessID'");
  159. } else {
  160. $res = $hander->exec('INSERT INTO ' . $this->sessionTable . " ( session_id, session_expire, session_data, update_time) VALUES( '$sessID', '$expire', '$sessData', '" . time() . "')");
  161. }
  162. if ($res) {
  163. return true;
  164. }
  165. return false;
  166. }
  167. /**
  168. * 删除Session.
  169. *
  170. * @param string $sessID
  171. */
  172. public function destroy($sessID)
  173. {
  174. $hander = is_array($this->hander) ? $this->hander[0] : $this->hander;
  175. $res = $hander->exec('DELETE FROM ' . $this->sessionTable . " WHERE session_id = '$sessID'");
  176. if ($res) {
  177. return true;
  178. }
  179. return false;
  180. }
  181. /**
  182. * Session 垃圾回收.
  183. *
  184. * @param string $sessMaxLifeTime
  185. */
  186. public function gc($sessMaxLifeTime)
  187. {
  188. $hander = is_array($this->hander) ? $this->hander[0] : $this->hander;
  189. return $hander->exec('DELETE FROM ' . $this->sessionTable . ' WHERE session_expire < ' . time());
  190. }
  191. }