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


Posted in PHP onJanuary 10, 2008

之前写过两篇文章《自定义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 相关文章推荐
PHP 面向对象 final类与final方法
May 05 PHP
检查php文件中是否含有bom的函数
May 31 PHP
thinkphp控制器调度使用示例
Feb 24 PHP
phpMyAdmin自动登录和取消自动登录的配置方法
May 12 PHP
CodeIgniter配置之routes.php用法实例分析
Jan 19 PHP
Symfony2获取web目录绝对路径、相对路径、网址的方法
Nov 14 PHP
总结PHP代码规范、流程规范、git规范
Jun 18 PHP
PHP实现的简单留言板功能示例【基于thinkPHP框架】
Dec 07 PHP
在 Laravel 项目中使用 webpack-encore的方法
Jul 21 PHP
PHP 代码简洁之道(小结)
Oct 16 PHP
PHP单元测试配置与使用方法详解
Dec 27 PHP
PHP安全之register_globals的on和off的区别
Jul 23 PHP
Http 1.1 Etag 与 Last-Modified提高php效率
Jan 10 #PHP
PHP读取目录下所有文件的代码
Jan 07 #PHP
台湾中原大学php教程孙仲岳主讲
Jan 07 #PHP
修改php.ini实现Mysql导入数据库文件最大限制的修改方法
Dec 11 #PHP
php下过滤HTML代码的函数
Dec 10 #PHP
php字符串截取中文截取2,单字节截取模式
Dec 10 #PHP
php获得当前的脚本网址
Dec 10 #PHP
You might like
php中get_cfg_var()和ini_get()的用法及区别
2015/03/04 PHP
PHP中Session可能会引起并发问题
2015/06/26 PHP
Yii2中事务的使用实例代码详解
2016/09/07 PHP
javascript 解析后的xml对象的读取方法细解
2009/07/25 Javascript
javascript实现tabs选项卡切换效果(自写原生js)
2013/03/19 Javascript
js中事件的处理与浏览器对象示例介绍
2013/11/29 Javascript
js实现点击左右按钮轮播图片效果实例
2015/01/29 Javascript
轻松学习jQuery插件EasyUI EasyUI表单验证
2015/12/01 Javascript
实例详解JavaScript获取链接参数的方法
2016/01/01 Javascript
BootStrap整体框架之基础布局组件
2016/12/15 Javascript
vue2实现移动端上传、预览、压缩图片解决拍照旋转问题
2017/04/13 Javascript
解决VUEX兼容IE上的报错问题
2018/03/01 Javascript
nodejs爬虫初试superagent和cheerio
2018/03/05 NodeJs
webpack 模块热替换原理
2018/04/09 Javascript
jQuery实现模糊查询的方法分析
2018/05/10 jQuery
Vue渲染过程浅析
2019/03/14 Javascript
通过JQuery,JQueryUI和Jsplumb实现拖拽模块
2019/06/18 jQuery
使用vue for时为什么要key【推荐】
2019/07/11 Javascript
微信小程序基于高德地图API实现天气组件(动态效果)
2020/10/22 Javascript
Python cookbook(数据结构与算法)筛选及提取序列中元素的方法
2018/03/19 Python
python3+PyQt5实现自定义分数滑块部件
2018/04/24 Python
Python 字符串与二进制串的相互转换示例
2018/07/23 Python
numpy库与pandas库axis=0,axis= 1轴的用法详解
2019/05/27 Python
Python3之字节串bytes与字节数组bytearray的使用详解
2019/08/27 Python
python+opencv3生成一个自定义纯色图教程
2020/02/19 Python
使用Keras实现Tensor的相乘和相加代码
2020/06/18 Python
Python读写锁实现实现代码解析
2020/11/28 Python
Django视图类型总结
2021/02/17 Python
上海微创软件面试题
2012/06/14 面试题
项目经理岗位职责
2013/11/11 职场文书
外贸业务员岗位职责
2013/11/24 职场文书
高中生家长会演讲稿
2014/01/14 职场文书
初中国旗下的演讲稿
2014/08/28 职场文书
个人自我剖析材料
2014/09/30 职场文书
有关花店创业的计划书模板
2019/08/27 职场文书
left join、inner join、right join的区别
2021/04/05 MySQL