zoukankan      html  css  js  c++  java
  • 数据库保存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

    CREATE TABLE `session` (  
      `session_id` varchar(32) NOT NULL default '',  
      `session_content` text NOT NULL,  
      `last_visit` int(11) NOT NULL,  
      PRIMARY KEY (`session_id`)  
    ) ENGINE=MyISAM; 
    此处建议使用ENGINE=MEMORY,MEMORY引擎采用内存表,所有数据存储在内存,操作速度快,对于session这种形式的数据正好适用。

    session.php

    <?PHP   
    // --------------------------------------------------------------------------  
    // File name   : session.php  
    // Description : 数据库存放session  
    // Copyright(C), MagicLab.cn, 2008, All Rights Reserved.  
    // Author: xinglu   QQ:330708730   MSN:xinglu_1983@hotmail.com  
    // --------------------------------------------------------------------------  
    class Session {  
    	var $lifeTime;  
    	var $domain;  
    	var $dbh;  
    	function __construct()  
    	{  
    		//定义生存期  
    		$this->lifeTime = 3600;  
    		//定义域  
    		$this->domain = $_SERVER['SERVER_NAME'];  
    		try   
    		{  
    			$this->dbh = new PDO('mysql:host=localhost;dbname=session', 'root', '');  
    			$this->dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);  
    			//PDO出错方式 跑出异常  
    			$this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);  
    		}  
    		catch (PDOException $e)  
    		{  
    			throw $e;  
    		}  
      
    		//设置session生存期  
    		ini_set('session.gc_maxlifetime',  $this->lifeTime);  
      
    		//设置客户端使用COOKIE保存SESSIONID  
    		ini_set('session.use_cookies', 1);  
    		ini_set('session.cookie_path', '/');  
      
    		//多主机共享保存SESSIONID的COOKIE(使二级域名可以共享session)
    		ini_set('session.cookie_domain', $this->domain);  
      
    		//设置客户端保存 SESSIONID 的cookie的生存期  
    		ini_set('session.cookie_lifetime', $this->lifeTime);  
      
    		//为保持客户端cookie生命期与服务端session生命期相同,进行写cookie操作  
    		$sessionid = session_id();  
    		$sessionname = session_name();  
    		setcookie($sessionname, $sessionid, $this->lifeTime, '/', $this->domain);  
      
    		//将session.save_handler设置为user,而不是默认的 files  
    		session_module_name('user');  
    		  
    		//重载session函数  
    		session_set_save_handler(array(&$this,"open"),  
    					array(&$this,"close"),  
    					array(&$this,"read"),  
    					array(&$this,"write"),  
    					array(&$this,"destroy"),  
    					array(&$this,"gc")  
    					);  
      
    	}  
      
    	function open($savePath, $sessName)   
    	{  
    		$this->gc();  
    		return true;  
    	}  
      
    	function close()   
    	{  
    		$this->gc();  
    		unset($this->dbh);  
    		return true;  
    	}  
      
    	function read($session_id)   
    	{  
    		if (!isset($session_id))   
    			return "";  
      
    		$last = time() - $this->lifeTime;  
      
    		$sql = sprintf("SELECT session_content  
    						FROM session 
    						WHERE session_id = '%s'  
    							AND last_visit > ".$last  
    						,$session_id);  
    		try  
    		{  
    			$query = $this->dbh->query($sql);  
    			if($row = $query->fetch(PDO::FETCH_ASSOC))  
    			return $row['session_content'];  
    		}  
    		catch(PDOException $e)  
    		{  
    			echo $e->getMessage();  
    			die();  
    		}  
    		return "";  
    	}  
      
    	function write($session_id, $session_content)   
    	{  
    		if (!isset($session_id))   
    			return "";  
      
    		$sql = sprintf("SELECT * FROM session WHERE session_id='%s'", $session_id);  
    		  
    		try  
    		{  
    			$sth = $this->dbh->query($sql);  
    			$rs = $sth->fetchAll(PDO::FETCH_ASSOC);  
    			if (is_array($rs) && !empty($rs))  
    			{  
    				$sql = sprintf("UPDATE session  
    								SET session_content='%s',last_visit=%d  
    								WHERE session_id='%s';"  
    								,$session_content  
    								,time()  
    								,$session_id  
    								);  
    			}  
    			else  
    			{  
    				$sql = sprintf("INSERT INTO session  
    								SET session_id='%s',session_content='%s',last_visit=%d;"  
    								,$session_id  
    								,$session_content  
    								,time()  
    								);  
    			}  
      
    			$rs = $this->dbh->exec($sql);  
    			if($rs)  
    				return true;  
    		}  
    		catch(PDOException $e)  
    		{  
    			echo $e->getMessage();  
    			die();  
    		}  
    		return false;  
    	}  
      
    	function destroy($session_id)   
    	{  
    		if (!isset($session_id))   
    			return true;  
      
    		$sql = sprintf("DELETE FROM session WHERE session_id = '%s'", $session_id);  
    		try  
    		{  
    			$rs = $this->dbh->exec($sql);  
    			if($rs)  
    			return true;  
    		}  
    		catch(PDOException $e)  
    		{  
    			echo $e->getMessage();  
    			die();  
    		}  
    		return false;  
    	}  
      
    	function gc()   
    	{  
    		$last = time() - $this->lifeTime;  
    		$sql = sprintf("DELETE FROM session WHERE last_visit < ".$last);  
    		$sth = $this->dbh->exec($sql);  
    		return $sth;  
    	}  
    }  
      
    ?>  
    
    使用方法:
    test.php

    <?php  
    require_once('session.php');  
    $session = new Session;  
    session_start();  
    ?>
    类文件里有一个有些特别的地方:

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


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

  • 相关阅读:
    php排序算法-冒泡排序
    Mac安装java JDK
    mysql索引简单记录一下
    Mac 通过 pecl安装 redis 扩展
    Mac通过pecl安装swool时遇到的坑(root + openssl)
    php获取两个日期的之间的日期信息,返回数组
    2021.4.9训练
    王道数据结构代码:双向链表的操作
    王道数据结构代码:单链表的操作
    PTA 7-1 大炮打蚊子 (15 分)
  • 原文地址:https://www.cnblogs.com/moqiang02/p/4061122.html
Copyright © 2011-2022 走看看