优化使用mysql存储session的php代码

5年以前  |  阅读数:1043 次  |  编程语言: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);    
}    

}
?>

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

 相关文章:
PHP分页显示制作详细讲解
SSH 登录失败:Host key verification failed
获取IMSI
将二进制数据转为16进制以便显示
获取IMEI
文件下载
贪吃蛇
双位运算符
PHP自定义函数获取搜索引擎来源关键字的方法
Java生成UUID
发送邮件
年的日历图
提取后缀名
在Zeus Web Server中安装PHP语言支持
让你成为最历害的git提交人
Yii2汉字转拼音类的实例代码
再谈PHP中单双引号的区别详解
指定应用ID以获取对应的应用名称
Python 2与Python 3版本和编码的对比
php封装的page分页类完整实例