优化使用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 daddslashes()和 saddslashes()有哪些区别分析
Oct 26 PHP
PHP 获取文件路径(灵活应用__FILE__)
Feb 15 PHP
php 强制下载文件实现代码
Oct 28 PHP
php中过滤非法字符的具体实现
Oct 29 PHP
PHP的fsockopen、pfsockopen函数被主机商禁用的解决办法
Jul 08 PHP
thinkphp文件引用与分支结构用法实例
Nov 26 PHP
浅析ThinkPHP缓存之快速缓存(F方法)和动态缓存(S方法)(日常整理)
Oct 26 PHP
微信 开发生成带参数的二维码的实例
Nov 23 PHP
PHP基于curl post实现发送url及相关中文乱码问题解决方法
Nov 25 PHP
PHP常用字符串函数小结(推荐)
Aug 05 PHP
PHP设计模式之建造者模式定义与用法简单示例
Aug 13 PHP
Laravel5.5 视图 - 创建视图和数据传递示例
Oct 21 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
菜鸟修复电子管记
2021/03/02 无线电
Php Cookie的一个使用注意点
2008/11/08 PHP
php 深入理解strtotime函数的使用详解
2013/05/23 PHP
自制PHP框架之模型与数据库
2017/05/07 PHP
javascript div 遮罩层封锁整个页面
2009/07/10 Javascript
js实现简单的星级选择器提交效果适用于评论等
2013/10/18 Javascript
基于iframe实现类似于ajax的页面无刷新
2014/05/31 Javascript
JavaScript中创建字典对象(dictionary)实例
2015/03/31 Javascript
Underscore.js 1.3.3 中文注释翻译说明
2015/06/25 Javascript
jquery控制显示服务器生成的图片流
2015/08/04 Javascript
jquery控制页面的展开和隐藏实现方法(推荐)
2016/10/15 Javascript
使用vue.js实现联动效果的示例代码
2017/01/10 Javascript
JavaScript体验异步更好的解决办法
2018/01/08 Javascript
iview通过Dropdown(下拉菜单)实现的右键菜单
2018/10/26 Javascript
基于elementUI实现图片预览组件的示例代码
2019/03/31 Javascript
vue设置动态请求地址的例子
2019/11/01 Javascript
[03:42]2014DOTA2西雅图国际邀请赛 Navi战队巡礼
2014/07/07 DOTA
python实现获取序列中最小的几个元素
2014/09/25 Python
Python中浅拷贝copy与深拷贝deepcopy的简单理解
2018/10/26 Python
学习python的前途 python挣钱
2019/02/27 Python
详解10个可以快速用Python进行数据分析的小技巧
2019/06/24 Python
Python关于__name__属性的含义和作用详解
2020/02/19 Python
使用卷积神经网络(CNN)做人脸识别的示例代码
2020/03/27 Python
详解HTML5中的标签
2015/06/19 HTML / CSS
美国在线工具商店:Acme Tools
2018/06/26 全球购物
美国在线面料商店:Online Fabric Store
2018/07/26 全球购物
俄罗斯小米家用电器、电子产品和智能家居商店:Poood.ru
2020/04/03 全球购物
25岁生日感言
2014/01/13 职场文书
中层干部培训方案
2014/06/16 职场文书
2014年四风问题个人对照自查剖析材料
2014/09/15 职场文书
2014年小学校长工作总结
2014/12/08 职场文书
实习单位指导教师评语
2014/12/30 职场文书
追悼词范文大全
2015/06/23 职场文书
工作简报格式范文
2015/07/21 职场文书
导游词之山东八仙过海景区
2019/11/11 职场文书
JavaScript 数组去重详解
2021/09/15 Javascript