Welcome

首页 / 网页编程 / PHP / 优化使用mysql存储session的php代码

之前写过两篇文章《自定义SESSION(二)——数据库保存》和《我为什么不使用session》
  但后来发现都有问题。前者处理在实际中几乎没什么用处,而且session回收还得自己另外处理。后者频繁的操作数据库,打来了很大的性能问题。

  这两天仔细考虑下,大致给出一个方案,但还没有具体详细的测试。
  1、session处理和统计结合起来。同时游客也都有记录。
  2、完全使用数据库和cookie来模拟session的功能。
  3、用户的对session的操作都尽量保证在一条sql语句完成。不用到session的时候,绝对不多一条查询。
  4、为了效率起见,session的回收没有集成进来,但提供了接口,可以调用实现。

暂时给出代码,不具体解释。
sql



CREATE TABLE `*****_session` (
 `sid` char(32) NOT NULL,
 `uid` int(10) NOT NULL,
 `username` char(32) NOT NULL,
 `usertype` tinyint(1) NOT NULL,
 `activetime` int(10) NOT NULL,
 `expiry` int(10) NOT NULL,
 `ip` char(15) NOT NULL,
 `url` char(80) NOT NULL,
 `value` char(255) NOT NULL,
 PRIMARY KEY  (`sid`)
) ENGINE=MEMORY DEFAULT CHARSET=utf8;




php代码

<? 
class session{ 

    private $_sessionPrex= "";//session的前缀 

    private $_time = "";//当前时间 

    private $_model = null;//数据库操作模型 

    private $_expiry = 1200;//session有效时间 

    private $_domain = "";//session的作用域 

    protected $isNew = 0;//判定操作动作 0 更新 1 增加 

    protected $session = array();//对应的一条session记录 

    public function __construct($options){ 
        $this->_setOptions($options); 
        if(empty($this->_time))$this->_time = time(); 
        $this->session["activetime"] = $this->_time; 
    } 

    public function start(){ 
        $this->_getSid(); 
    } 

    public function set($key,$value){ 
        if(in_array($key,array("uid","username","usertype","url","expiry"))){ 
            if($key == "expiry"){ 
                $this->_setCookie($this->_sessionPrex."_sid",$this->session["sid"],$value); 
                $this->_setCookie($this->_sessionPrex."_uid",$this->session["uid"],$value); 
            } 
            $this->session[$key] = $value; 
        }else{ 
            $other = $this->session["value"]; 
            $other[$key] = $value; 
            $this->session["value"] = $other; 
        } 
    } 

    public function get($key){ 
        if(in_array($key,array("uid","username","usertype","url","expiry"))){ 
            return $this->session[$key]; 
        }else{ 
            if(isset($this->session["value"][$key])){ 
                return $this->session["value"][$key]; 
            } 
            return null; 
        } 
    } 

    public function gc($file,$time = 1200){ 
        $lasttime = file_get_contents($file); 
        if($lasttime + $time<$this->_time){ 
            file_put_contents($file,$this->_time); 
            return $this->_model->delete("activetime+expiry<".$this->_time); 
        } 
    } 

    public function destroy(){ 
        $this->session["uid"] = 0; 
        $this->session["username"] = ""; 
        $this->session["usertype"] = -1; 
        $this->session["expiry"] = $this->_expiry; 
        $this->session["value"] = array(); 
        $this->_setCookie($this->_sessionPrex."_sid",$this->session["sid"],$this->_expiry); 
        $this->_setCookie($this->_sessionPrex."_uid",$this->session["uid"],$this->_expiry); 
    } 

    public function __destruct(){ 
        $this->_save(); 
    } 

    private function _save(){ 
        $dbSession = $this->session; 
        $dbSession["value"] = serialize($dbSession["value"]); 
        if(strlen($dbSession["value"])>255)$this->_error("session->value is too long!"); 
        if($this->isNew == 1){ 
            //增加 
            $this->_model->insert($dbSession); 
        }else{ 
            //更新 
            $sid = $dbSession["sid"]; 
            $this->_model->update(array_slice($dbSession,1),"sid="".$sid."""); 
        } 
    } 

    private function _getSession($sid){ 
        $dbSession = $this->_model->detail("sid = "".$sid."""); 
        if(!$dbSession)return false; 
        $dbSession["value"] = unserialize($dbSession["value"]); 
        $this->session = array_merge($dbSession,$this->session);         
        return true; 
    } 

    private function _getSid(){ 
        $sid = strip_tags($_COOKIE[$this->_sessionPrex."_sid"]); 
        if(strlen($sid)==32){ 
            if($this->_getSession($sid)){ 
                return true; 
            } 
        }else{ 
            $sid = md5(time().mt_rand(1000,10000)); 
            $this->_setCookie($this->_sessionPrex."_sid",$sid); 
        } 
        $this->_setCookie($this->_sessionPrex."_uid",0); 
        $this->session = array( 
                "uid" => 0, 
                "username" => "", 
                "usertype" => -1, 
                "activetime" => $this->_time, 
                "ip" => $this->_getip(), 
                "url" => strip_tags($_SERVER["REQUEST_URI"]), 
                "expiry" =>$this->_expiry, 
                "value" => array() 
        ); 
        $this->isNew = 1; 
        $this->session["sid"] = $sid; 
    } 

    private function _setCookie($name,$value,$expiry=0){ 
        if(empty($expiry))$expiry = $this->_expiry; 
        if(empty($this->_domain)){ 
            setcookie($name,$value,$this->_time + $expiry,"/"); 
        }else{ 
            setcookie($name,$value,$this->_time + $expiry,"/",$this->_domain); 
        } 
    } 

    private function _getip(){ 
        return getip(); 
    } 

    private function _setOptions($options){ 
        foreach ($options as $key=>$value){ 
            if(in_array($key,array("sessionPrex","time","model","expiry","domain"))){ 
                $key = "_".$key; 
                $this->$key = $value; 
            } 
        } 
    } 

    private function _error($msg){ 
        throw new Phpbean_Exception($msg); 
    } 

?> 

(注意,该代码不能直接使用,本文主要是提供一种思路)