用数据库保存session

一般情况下,php.ini里的session.save_handler默认是file,也就是用文件来保存session,这种方式有几个缺点:

1、如果单靠session自己的垃圾回收机制,时间久了,保存session的文件会越来越多,影响查找效率;

2、对于需要统计同时在线用户的系统,实现起来很不方便;

3、分布式系统难以共享session。

如果将session.save_handler设置为user,php可以通过session_set_save_handler函数来重载session的几个底层会话处理方法,以达到使用数据库来保存session的目的,下面以mysql数据库为例,数据库连接方式采用PDO。

 

session.sql

 

  1. CREATE TABLE `session` (  
  2.   `session_id` varchar(32) NOT NULL default '',  
  3.   `session_content` text NOT NULL,  
  4.   `last_visit` int(11) NOT NULL,  
  5.   PRIMARY KEY (`session_id`)  
  6. ) TYPE=MyISAM;  

 

 

 

session.php

 

  1. <?PHP   
  2. // --------------------------------------------------------------------------  
  3. // File name   : session.php  
  4. // Description : 数据库存放session  
  5. // Copyright(C), MagicLab.cn, 2008, All Rights Reserved.  
  6. // Author: xinglu   QQ:330708730   MSN:xinglu_1983@hotmail.com  
  7. // --------------------------------------------------------------------------  
  8. class Session {  
  9.     var $lifeTime;  
  10.     var $domain;  
  11.     var $dbh;  
  12.     function __construct()  
  13.     {  
  14.         //定义生存期  
  15.         $this->lifeTime = 3600;  
  16.         //定义域  
  17.         $this->domain = $_SERVER['SERVER_NAME'];  
  18.         try   
  19.         {  
  20.             $this->dbh = new PDO('mysql:host=localhost;dbname=session', 'root', '');  
  21.             $this->dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);  
  22.             //PDO出错方式 跑出异常  
  23.             $this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);  
  24.         }  
  25.         catch (PDOException $e)  
  26.         {  
  27.             throw $e;  
  28.         }  
  29.   
  30.         //设置session生存期  
  31.         ini_set('session.gc_maxlifetime',  $this->lifeTime);  
  32.   
  33.         //设置客户端使用COOKIE保存SESSIONID  
  34.         ini_set('session.use_cookies', 1);  
  35.         ini_set('session.cookie_path', '/');  
  36.   
  37.         //多主机共享保存SESSIONID的COOKIE  
  38.         ini_set('session.cookie_domain', $this->domain);  
  39.   
  40.         //设置客户端保存 SESSIONID 的cookie的生存期  
  41.         ini_set('session.cookie_lifetime', $this->lifeTime);  
  42.   
  43.         //为保持客户端cookie生命期与服务端session生命期相同,进行写cookie操作  
  44.         $sessionid = session_id();  
  45.         $sessionname = session_name();  
  46.         setcookie($sessionname, $sessionid, $this->lifeTime, '/', $this->domain);  
  47.   
  48.         //将session.save_handler设置为user,而不是默认的 files  
  49.         session_module_name('user');  
  50.           
  51.         //重载session函数  
  52.         session_set_save_handler(array(&$this,"open"),  
  53.                                  array(&$this,"close"),  
  54.                                  array(&$this,"read"),  
  55.                                  array(&$this,"write"),  
  56.                                  array(&$this,"destroy"),  
  57.                                  array(&$this,"gc")  
  58.                                 );  
  59.   
  60.     }  
  61.   
  62.     function open($savePath, $sessName)   
  63.     {  
  64.         $this->gc();  
  65.         return true;  
  66.     }  
  67.   
  68.     function close()   
  69.     {  
  70.         $this->gc();  
  71.         unset($this->dbh);  
  72.         return true;  
  73.     }  
  74.   
  75.     function read($session_id)   
  76.     {  
  77.         if (!isset($session_id))   
  78.             return "";  
  79.   
  80.         $last = time() - $this->lifeTime;  
  81.   
  82.         $sql = sprintf("SELECT session_content  
  83.                         FROM session 
  84.                         WHERE session_id = '%s'  
  85.                             AND last_visit > ".$last  
  86.                         ,$session_id);  
  87.         try  
  88.         {  
  89.             $query = $this->dbh->query($sql);  
  90.             if($row = $query->fetch(PDO::FETCH_ASSOC))  
  91.             return $row['session_content'];  
  92.         }  
  93.         catch(PDOException $e)  
  94.         {  
  95.             echo $e->getMessage();  
  96.             die();  
  97.         }  
  98.         return "";  
  99.     }  
  100.   
  101.     function write($session_id, $session_content)   
  102.     {  
  103.         if (!isset($session_id))   
  104.             return "";  
  105.   
  106.         $sql = sprintf("SELECT * FROM session WHERE session_id='%s'", $session_id);  
  107.           
  108.         try  
  109.         {  
  110.             $sth = $this->dbh->query($sql);  
  111.             $rs = $sth->fetchAll(PDO::FETCH_ASSOC);  
  112.             if (is_array($rs) && !empty($rs))  
  113.             {  
  114.                 $sql = sprintf("UPDATE session  
  115.                                 SET session_content='%s',last_visit=%d  
  116.                                 WHERE session_id='%s';"  
  117.                                 ,$session_content  
  118.                                 ,time()  
  119.                                 ,$session_id  
  120.                                 );  
  121.             }  
  122.             else  
  123.             {  
  124.                 $sql = sprintf("INSERT INTO session  
  125.                                 SET session_id='%s',session_content='%s',last_visit=%d;"  
  126.                                 ,$session_id  
  127.                                 ,$session_content  
  128.                                 ,time()  
  129.                                 );  
  130.             }  
  131.   
  132.             $rs = $this->dbh->exec($sql);  
  133.             if($rs)  
  134.                 return true;  
  135.         }  
  136.         catch(PDOException $e)  
  137.         {  
  138.             echo $e->getMessage();  
  139.             die();  
  140.         }  
  141.         return false;  
  142.     }  
  143.   
  144.     function destroy($session_id)   
  145.     {  
  146.         if (!isset($session_id))   
  147.             return true;  
  148.   
  149.         $sql = sprintf("DELETE FROM session WHERE session_id = '%s'", $session_id);  
  150.         try  
  151.         {  
  152.             $rs = $this->dbh->exec($sql);  
  153.             if($rs)  
  154.             return true;  
  155.         }  
  156.         catch(PDOException $e)  
  157.         {  
  158.             echo $e->getMessage();  
  159.             die();  
  160.         }  
  161.         return false;  
  162.     }  
  163.   
  164.     function gc()   
  165.     {  
  166.         $last = time() - $this->lifeTime;  
  167.         $sql = sprintf("DELETE FROM session WHERE last_visit < ".$last);  
  168.         $sth = $this->dbh->exec($sql);  
  169.         return $sth;  
  170.     }  
  171. }  
  172.   
  173. ?>  

 

 

使用方法:

test.php

 

  1. <?php  
  2. require_once('session.php');  
  3. $session = new Session;  
  4. session_start();  
  5. ?>  

 

 

 类文件里有一个有些特别的地方:

PHP代码

 

  1. //为保持客户端cookie生命期与服务端session生命期相同,进行写cookie操作  
  2. $sessionid = session_id();  
  3. $sessionname = session_name();  
  4. setcookie($sessionname, $sessionid, $this->lifeTime, '/', $this->domain);  

 

如果只是单单将session.gc_maxlifetime和session.cookie_lifetime的设置成相同的时间,那么以后在每次session_start()的时候,服务端session的生存期都会自动得到延长,但是保存sessionid的cookie却没有。当然,也可以直接将session.cookie_lifetime设置成一个非常大的数,只是这样显得比较霸道

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值