优化使用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中的观察者模式
Mar 24 PHP
如何在symfony中导出为CSV文件中的数据
Oct 06 PHP
PHP中的按位与和按位或操作示例
Jan 27 PHP
如何在HTML 中嵌入 PHP 代码
May 13 PHP
PHP实现过滤各种HTML标签
May 17 PHP
php header函数的常用http头设置
Jun 25 PHP
从性能方面考虑PHP下载远程文件的3种方法
Dec 29 PHP
关于PHP定时发送服务的解决办法
Apr 23 PHP
Laravle eloquent 多对多模型关联实例详解
Nov 22 PHP
PHP基于SPL实现的迭代器模式示例
Apr 22 PHP
Yii框架模拟组件调用注入示例
Nov 11 PHP
PHP中用Trait封装单例模式的实现
Dec 18 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
下拉列表多级联动dropDownList示例代码
2013/06/27 PHP
php一维二维数组键排序方法实例总结
2014/11/13 PHP
PHP中使用正则表达式提取中文实现笔记
2015/01/20 PHP
php无限分类使用concat如何实现
2015/11/05 PHP
写了一个layout,拖动条连贯,内容区可为iframe
2007/08/19 Javascript
jQueryUI如何自定义组件实现代码
2010/11/14 Javascript
JS禁用浏览器退格键实现思路及代码
2013/10/29 Javascript
JavaScript中操作字符串之localeCompare()方法的使用
2015/06/06 Javascript
js实现简单的联动菜单效果
2015/08/19 Javascript
深入理解bootstrap框架之第二章整体架构
2016/10/09 Javascript
Angular 4环境准备与Angular cli创建项目详解
2017/05/27 Javascript
基于JavaScript实现飘落星星特效
2017/08/10 Javascript
Node.js利用断言模块assert进行单元测试的方法
2017/09/28 Javascript
网页爬虫之cookie自动获取及过期自动更新的实现方法
2018/03/06 Javascript
Vue如何实现响应式系统
2018/07/11 Javascript
vue-router懒加载速度缓慢问题及解决方法
2018/11/25 Javascript
koa+jwt实现token验证与刷新功能
2019/05/30 Javascript
微信小程序中悬浮窗功能的实现代码
2019/08/02 Javascript
JavaScript实现表单验证功能
2020/12/09 Javascript
[04:03]2014DOTA2西雅图国际邀请赛 LGD战队巡礼
2014/07/07 DOTA
举例详解Python中循环语句的嵌套使用
2015/05/14 Python
利用python微信库itchat实现微信自动回复功能
2017/05/18 Python
python迭代dict的key和value的方法
2018/07/06 Python
Python实现的统计文章单词次数功能示例
2019/07/08 Python
python实现简易学生信息管理系统
2020/04/05 Python
Python tkinter三种布局实例详解
2020/01/06 Python
浅谈matplotlib 绘制梯度下降求解过程
2020/07/12 Python
Java语言程序设计测试题改错题部分
2014/07/22 面试题
护士毕业生自我鉴定
2014/02/08 职场文书
银行求职信怎么写
2014/05/26 职场文书
运动会主持词大全
2015/07/02 职场文书
朋友聚会祝酒词
2015/08/10 职场文书
2016年毕业实习心得体会范文
2015/10/09 职场文书
如何制定销售人员薪酬制度?
2019/07/09 职场文书
《文化苦旅》读后感:阅读,让人诗意地栖居在大地上
2019/12/24 职场文书
python编写五子棋游戏
2021/05/25 Python