优化使用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 增加了对 .ZIP 文件的读取功能
Oct 09 PHP
解析wamp5下虚拟机配置文档
Jun 27 PHP
php导出csv格式数据并将数字转换成文本的思路以及代码分享
Jun 05 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(十三)
Jun 26 PHP
discuz目录文件资料汇总
Dec 30 PHP
19个Android常用工具类汇总
Dec 30 PHP
phplot生成图片类用法详解
Jan 06 PHP
PHP+apc+ajax实现的ajax_upload上传进度条代码
Jan 25 PHP
php连接oracle数据库的核心步骤
May 26 PHP
PHP微信刮刮卡 附微信接口
Jul 22 PHP
php中foreach结合curl实现多线程的方法分析
Sep 22 PHP
PHP+redis实现微博的推模型案例分析
Jul 10 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
在WIN98下以apache模块方式安装php
2006/10/09 PHP
ThinkPHP利用PHPMailer实现邮件发送实现代码
2013/09/26 PHP
PHP实现的随机红包算法示例
2017/08/14 PHP
Laravel jwt 多表(多用户端)验证隔离的实现
2019/12/18 PHP
javascript 选择文件夹对话框(web)
2009/07/07 Javascript
Extjs中DisplayField的日期或者数字格式化扩展
2010/09/03 Javascript
jquery 学习之一 对象访问
2010/11/23 Javascript
基于jquery的地址栏射击游戏代码
2011/03/10 Javascript
js格式化时间小结
2014/11/03 Javascript
JSONObject使用方法详解
2015/12/17 Javascript
jquery+json实现动态商品内容展示的方法
2016/01/14 Javascript
javascript加载xml 并解析各节点的值(实现方法)
2016/10/12 Javascript
详解javascript立即执行函数表达式IIFE
2017/02/13 Javascript
详解用node搭建简单的静态资源管理器
2017/08/09 Javascript
详解使用Vue Router导航钩子与Vuex来实现后退状态保存
2017/09/11 Javascript
基于js中的原型(全面讲解)
2017/09/19 Javascript
简单谈谈Python中函数的可变参数
2016/09/02 Python
对Python中gensim库word2vec的使用详解
2018/05/08 Python
Python(Django)项目与Apache的管理交互的方法
2018/05/16 Python
对Python中plt的画图函数详解
2018/11/07 Python
python通过tcp发送xml报文的方法
2018/12/28 Python
pyqt5 QlistView列表显示的实现示例
2020/03/24 Python
使用npy转image图像并保存的实例
2020/07/01 Python
python 获取计算机的网卡信息
2021/02/18 Python
用python 绘制茎叶图和复合饼图
2021/02/26 Python
CSS3 渐变(Gradients)之CSS3 线性渐变
2016/07/08 HTML / CSS
美国首屈一指的礼品篮供应商:GiftTree
2018/01/06 全球购物
电大自我鉴定
2013/10/27 职场文书
公务员爱岗敬业演讲稿
2014/08/26 职场文书
信访工作汇报材料
2014/10/27 职场文书
办公室年度工作总结2015
2015/05/21 职场文书
交通安全学习心得体会
2016/01/18 职场文书
2019财务毕业实习报告
2019/06/27 职场文书
Python入门之使用pandas分析excel数据
2021/05/12 Python
Vue中foreach数组与js中遍历数组的写法说明
2021/06/05 Vue.js
浅析MySQL如何实现事务隔离
2021/06/26 MySQL