php实现session入库

为什么要把session存入数据库?有什么用?

可以:统计在线人数,现实多站点session共享(通行证),控制同个账号登入人数等。

要实现session的入库,有关键的几个基本知识:

session.gc_divisor = 100 session.gc_probability = 1 。session.gc_probability 与 session.gc_divisor 合起来用来管理 gc(garbage collection 垃圾回收)进程启动的概率。( session.gc_probability/session.gc_divisor = 概率)

session.gc_maxlifetime = 1024 。session.gc_maxlifetime 指定过了多少秒之后数据就会被视为“垃圾”并被清除。

session.save_handler = files 。session.save_handler 定义了来存储和获取与会话关联的数据的处理器的名字。默认为 files。参见 session_set_save_handler()

首先设计数据库表:

[sql]

CREATE TABLE IF NOT EXISTS `session` (

`phpsession` char(32) COLLATE utf8_bin NOT NULL,

`uptime` int(10) unsigned NOT NULL,

`data` text COLLATE utf8_bin NOT NULL, PRIMARY KEY (`phpsession`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

需要2个class, 一个是数据库的,一个是session的操作类

[php]view plaincopy

print?
  1. <?php
  2. /**
  3. * session入库操作类
  4. * @author 删代码工程师 geek-cy.com
  5. */
  6. include 'DbSession.php'; //引入session数据库操作类
  7. class MySession extends DbSession{
  8. private $dbc = null; //保存数据库资源句柄
  9. private $lifetime = null; // session的生成时间
  10. private $time = null; //当前时间
  11. const uptime = 30; //更新session的时间
  12. static $DEBUG = false; //是否开启错误提示
  13. public function __construct( ){
  14. $this->init();
  15. $this->SessionSetSaveHandler();
  16. }
  17. /**
  18. * 初始化session处理
  19. * @throws Exception
  20. */
  21. private function init(){
  22. try{
  23. //设置数据库链接资源句柄
  24. $db = DbSession::InitDbSession(); //获取用于数据库操作的对象
  25. if( !($db instanceof DbSession) ){
  26. throw new Exception('需要MySession类的对象');
  27. }else{
  28. $this->dbc = $db;
  29. }
  30. //设置session有效时间
  31. if( !$this->lifetime = ini_get('session.gc_maxlifetime') ){
  32. throw new Exception('session.gc_maxlifetime获取失败');
  33. }
  34. }catch (Exception $e){
  35. $this->ShowErrow( $e->getMessage() );
  36. }
  37. $this->time = time();
  38. // ini_set('session.save_handler', user);
  39. }
  40. /**
  41. * 设置自定义session的回调方法
  42. */
  43. private function SessionSetSaveHandler(){
  44. session_set_save_handler(
  45. array($this, "open"),
  46. array($this, "close"),
  47. array($this, "read"),
  48. array($this, "write"),
  49. array($this, "destroy"),
  50. array($this, "gc")
  51. );
  52. session_start();//开启session
  53. }
  54. /**
  55. * 打开session
  56. * @param string $savePath
  57. * @param string $sessName
  58. * @return boolean
  59. */
  60. public function open($savePath, $sessName){
  61. if(is_null( $this->dbc )){ //判断数据库连接是否正常
  62. return false;
  63. }else{
  64. return true;
  65. }
  66. }
  67. /**
  68. * 关闭session
  69. */
  70. public function close(){
  71. $this->gc($this->lifetime); //触发垃圾回收机制
  72. return $this->dbc->MysqlClose(); //关闭数据库连接
  73. }
  74. /**
  75. * 读取session
  76. * @param string $sessionid
  77. * @return boolean|unknown
  78. */
  79. public function read( $sessionid ){
  80. $selectData = array(0=>$this->phpsession,1=>$this->uptime,2=>$this->data); // 需要读取的字段,数组形式
  81. $sessionData = $this->dbc->ReadSession($sessionid, $selectData);
  82. //是否返回有效值
  83. if( $sessionData == false){
  84. return false;
  85. }
  86. //是否过期判断
  87. if( $sessionData[$this->uptime] + $this->lifetime < $this->time ){
  88. $this->destroy( $sessionData[$this->phpsession] );
  89. return false;
  90. }
  91. return $sessionData[$this->data];
  92. }
  93. /**
  94. * 写入session
  95. * @param string $sessionid
  96. * @param string $data
  97. * @return boolean
  98. */
  99. public function write( $sessionid, $data ){
  100. $selectData = array(0=>$this->phpsession,1=>$this->uptime,2=>$this->data);// 需要读取的字段,数组形式
  101. $sessionData = $this->dbc->ReadSession($sessionid, $selectData);
  102. if( $sessionData == false){ //没有session数据
  103. if( !empty( $data ) ){ //判断是否用需要插入的session值
  104. //数组形式组装要插入的字段和对应值
  105. $insertData = array(
  106. $this->phpsession => $sessionid,
  107. $this->uptime => $this->time,
  108. $this->data => $data
  109. );
  110. $this->dbc->InsertSession( $insertData );
  111. }
  112. }else{//已经有了session数据
  113. //判断session数据是否有改变,或者需要更新有效时间。
  114. if($sessionData[$this->data] != $data || $this->time > ($sessionData[$this->uptime]+self::uptime)){
  115. //以数组形式组装要更新的数据
  116. $updateData = array(
  117. $this->uptime => $this->time,
  118. $this->data => $data
  119. );
  120. $this->dbc->UpdateSession($sessionData[$this->phpsession], $updateData );
  121. }
  122. }
  123. return true;
  124. }
  125. /**
  126. * 销毁session
  127. * @param string $sessionid
  128. */
  129. public function destroy( $sessionid ){
  130. return $this->dbc->DeleteSession( $sessionid );
  131. }
  132. /**
  133. * session的回收机制
  134. * @param string $lifetime
  135. */
  136. public function gc( $lifetime ){
  137. $this->dbc->GcSession( $lifetime );
  138. }
  139. }
  140. ?>

[php]view plaincopy

print?
  1. <?php
  2. /**
  3. * session入库的数据库操作类
  4. * @author 删代码工程师 geek-cy.com
  5. *
  6. */
  7. class DbSession{
  8. public static $db = null;
  9. private $con = null; //保存数据库链接资源句柄
  10. private $HOSTNAME = 'localhost';
  11. private $DB = 'phptest';
  12. private $USER = 'root';
  13. private $PASSWORD = '';
  14. const CHARSET = 'UTF8'; //编码设置
  15. static $DEBUG = true; //是否开启错误提示
  16. //session表与表字段
  17. private $TableName = 'session';
  18. protected $phpsession = 'phpsession';
  19. protected $uptime = 'uptime';
  20. protected $data = 'data';
  21. private function __construct(){
  22. $this->contect();
  23. }
  24. private function __clone(){
  25. }
  26. /**
  27. * 初始化链接数据库
  28. * @return Ambigous <NULL, string>
  29. */
  30. public static function InitDbSession(){
  31. if( is_null(self::$db) || !(self::$db instanceof self) ){
  32. self::$db = new DbSession;
  33. }
  34. return self::$db; //返回类对象
  35. }
  36. /**
  37. * 链接数据库
  38. *
  39. */
  40. private function contect(){
  41. $this->con = mysql_connect($this->HOSTNAME, $this->USER, $this->PASSWORD); //保存数据库连接资源句柄
  42. try{
  43. if( is_null($this->con) ){
  44. throw new Exception('链接数据库失败');
  45. }
  46. if(!mysql_select_db($this->DB, $this->con)){
  47. throw new Exception('选择数据库失败');
  48. }
  49. mysql_query("SET NAMES self::CHARSET");
  50. }catch (Exception $e){
  51. $this->ShowErrow( $e->getMessage() );
  52. }
  53. }
  54. /**
  55. * 输出错误
  56. * @param string $msg
  57. */
  58. protected function ShowErrow( $msg ){
  59. if(static::$DEBUG){ //判断是否打印错误
  60. echo $msg;
  61. }
  62. }
  63. /**
  64. * 读取数据库中保存的session
  65. * @param string $sessionid
  66. * @param array $selectData
  67. * @return boolean|Ambigous <boolean, multitype:>
  68. */
  69. public function ReadSession( $sessionid, array $selectData ){
  70. $selectData = $this->doSelectData($selectData);
  71. if(!$selectData){
  72. return false;
  73. }
  74. if( $this->CheckSessionId($sessionid) ){
  75. $sql = 'SELECT '.$selectData.' FROM `'.$this->TableName.'` WHERE '.$this->phpsession.' = \''.$sessionid.'\' LIMIT 1';
  76. $result = mysql_query($sql, $this->con);
  77. return $this->fetch($result);
  78. }
  79. }
  80. /**
  81. * 写入新session到数据库中
  82. * @param array $insertData
  83. * @return boolean
  84. */
  85. public function InsertSession( array $insertData ){
  86. if( $insertData = $this->doInsertData($insertData) ){
  87. $sql = 'INSERT INTO '.$this->TableName.'('.$insertData[0].') VALUES('.$insertData[1].')';
  88. mysql_query($sql, $this->con);
  89. return true;
  90. }else{
  91. return false;
  92. }
  93. }
  94. /**
  95. * 更新数据库中保存的session
  96. * @param string $sessionid
  97. * @param array $updateData
  98. * @return boolean
  99. */
  100. public function UpdateSession( $sessionid, array $updateData){
  101. if( !$this->CheckSessionId($sessionid) ){
  102. return false;
  103. }
  104. if( $updateData = $this->doUpadateData($updateData) ){
  105. $sql = 'UPDATE '.$this->TableName.' SET '.$updateData.' WHERE '.$this->phpsession.' = \''.$sessionid.'\'';
  106. mysql_query($sql, $this->con);
  107. return true;
  108. }else{
  109. return false;
  110. }
  111. }
  112. /**
  113. * 删除数据库中的session
  114. * @param string $sessionid
  115. * @return boolean
  116. */
  117. public function DeleteSession( $sessionid ){
  118. if( !$this->CheckSessionId($sessionid) ){
  119. return false;
  120. }
  121. $sql = 'DELETE FROM '.$this->TableName.' WHERE \''.$sessionid.'\' = '.$this->phpsession;
  122. mysql_query($sql,$this->con);
  123. return true;
  124. }
  125. /**
  126. * 回收清除数据库中已经获取无用的session
  127. * @param string $lifetime
  128. * @return boolean
  129. */
  130. public function GcSession( $lifetime ){
  131. if( !ctype_digit($lifetime )){
  132. return false;
  133. }
  134. $checktime = time()-$lifetime;
  135. $sql = 'DELETE FROM '.$this->TableName.' WHERE '.$this->uptime.' < '.$checktime ;
  136. mysql_query($sql,$this->con);
  137. return true;
  138. }
  139. /**
  140. * 关闭数据库连接
  141. */
  142. public function MysqlClose(){
  143. mysql_close( $this->con );
  144. }
  145. public function __destruct(){
  146. self::$db = null;
  147. if($this->con instanceof self){
  148. mysql_close( $this->con );
  149. }
  150. }
  151. /**
  152. * 对session id 做合法性检查
  153. * @param string $sessionid
  154. * @return boolean
  155. */
  156. private function CheckSessionId( $sessionid ){
  157. return ctype_alnum($sessionid);
  158. }
  159. /**
  160. * 返回select取得的结果集
  161. * @param $result
  162. * @return boolean|multitype:
  163. */
  164. private function fetch( $result ){
  165. if( $result && mysql_num_rows($result) == 1){
  166. $resultArray = array();
  167. $resultArray = mysql_fetch_array($result, MYSQL_ASSOC);
  168. if( !$resultArray || count($resultArray)== 0 ){
  169. return false;
  170. }else{
  171. return $resultArray;
  172. }
  173. }else{
  174. return false;
  175. }
  176. }
  177. /**
  178. * 处理select要查询的字段
  179. * @param array $data
  180. * @return boolean|string
  181. */
  182. private function doSelectData( array $data ){
  183. $keyString = '';
  184. foreach ($data as $value){
  185. $keyString .= '`'.$value.'`,';
  186. }
  187. $keyString = substr($keyString,0,-1);
  188. if($keyString == ''){
  189. return false;
  190. }
  191. return $keyString;
  192. }
  193. /**
  194. * 处理要insert进数据库的字段和对应的值
  195. * @param array $data
  196. * @return boolean|string
  197. */
  198. private function doInsertData( array $data ){
  199. $keyString = '';
  200. $valueString = '';
  201. if(array_key_exists($this->phpsession, $data)){
  202. if( !$this->CheckSessionId($data[$this->phpsession]) ){
  203. return false;
  204. }
  205. }
  206. foreach ($data as $key => $value){
  207. $keyString .= '`'.$key.'`,';
  208. if(ctype_digit($value)){
  209. $valueString .= ''.$value.',';
  210. }else{
  211. $valueString .= '\''.$value.'\',';
  212. }
  213. }
  214. if( $keyString != '' && $valueString != ''){
  215. $keyString = substr($keyString,0,-1);
  216. $valueString = substr($valueString,0,-1);
  217. $dataArray[0] = $keyString; //字段
  218. $dataArray[1] = $valueString;//值
  219. return $dataArray;
  220. }else{
  221. return false;
  222. }
  223. }
  224. /**
  225. * 处理update的字段和对应的值
  226. * @param array $data
  227. * @return boolean|string
  228. */
  229. private function doUpadateData( array $data ){
  230. $upDataString = '';
  231. foreach($data as $key => $value){
  232. if(ctype_digit($value)){
  233. $value = ''.$value.'';
  234. }else{
  235. $value = '\''.$value.'\'';
  236. }
  237. $upDataString .= '`'.$key.'` = '.$value.',';
  238. }
  239. $upDataString = substr($upDataString,0,-1);
  240. if( $upDataString == ''){
  241. return false;
  242. }
  243. return $upDataString;
  244. }
  245. }

下面是使用方法:

[php]view plaincopy

print?
    1. <?php
    2. include 'MySession.php';
    3. $session = new MySession( );
    4. $_SESSION['test1'] = 'test1';
    5. $_SESSION['test2'] = 2;
    6. $_SESSION['test3'] = array(1,2,3,4);
    7. // session_destroy();
    8. ?>