优化使用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 中执行系统外部命令
Oct 09 PHP
社区(php&amp;&amp;mysql)二
Oct 09 PHP
FCKeditor的安装(PHP)
Jan 13 PHP
PHP生成excel时单元格内换行问题的解决方法
Aug 26 PHP
php开发环境配置记录
Jan 14 PHP
PHP和Mysqlweb应用开发核心技术-第1部分 Php基础-2 php语言介绍
Jul 03 PHP
PHP jQuery表单,带验证具体实现方法
Feb 15 PHP
PHP中读取文件的8种方法和代码实例
Aug 05 PHP
PHP 中TP5 Request 请求对象的实例详解
Jul 31 PHP
Laravel学习教程之IOC容器的介绍与用例
Aug 15 PHP
php从数据库读取数据,并以json格式返回数据的方法
Aug 21 PHP
laravel框架使用极光推送消息操作示例
Feb 15 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编程开发“虚拟域名”系统
2006/10/09 PHP
php4的session功能评述(二)
2006/10/09 PHP
php中判断一个字符串包含另一个字符串的方法
2007/03/19 PHP
PHP文件锁函数flock()详细介绍
2014/11/18 PHP
PHP入门教程之正则表达式基本用法实例详解(正则匹配,搜索,分割等)
2016/09/11 PHP
简单谈谈PHP面向对象之标识对象
2017/06/27 PHP
jquery利用event.which方法获取键盘输入值的代码
2011/10/09 Javascript
javascript编码的几个方法详细介绍
2013/01/06 Javascript
JSON 对象未定义错误的解决方法
2016/09/29 Javascript
js实现日期显示的一些操作(实例讲解)
2017/07/27 Javascript
浅谈React高阶组件
2018/03/28 Javascript
微信小程序冒泡事件及其阻止方法实例分析
2018/12/06 Javascript
详解Vue-cli3 项目在安卓低版本系统和IE上白屏问题解决
2019/04/14 Javascript
JavaScript中关于base64的一些事
2019/05/06 Javascript
p5.js绘制旋转的正方形
2019/10/23 Javascript
Vue中多元素过渡特效的解决方案
2020/02/05 Javascript
[01:09:13]DOTA2-DPC中国联赛 正赛 CDEC vs XG BO3 第三场 1月19日
2021/03/11 DOTA
python学习之编写查询ip程序
2016/02/27 Python
python抓取并保存html页面时乱码问题的解决方法
2016/07/01 Python
Matplotlib 生成不同大小的subplots实例
2018/05/25 Python
django之对FileField字段的upload_to的设定方法
2019/07/28 Python
pandas DataFrame的修改方法(值、列、索引)
2019/08/02 Python
Python高阶函数、常用内置函数用法实例分析
2019/12/26 Python
pycharm设置当前工作目录的操作(working directory)
2020/02/14 Python
在python3中实现更新界面
2020/02/21 Python
解决jupyter运行pyqt代码内核重启的问题
2020/04/16 Python
Python3 socket即时通讯脚本实现代码实例(threading多线程)
2020/06/01 Python
python海龟绘图之画国旗实例代码
2020/11/11 Python
Pam & Gela官网:美国性感前卫女装品牌
2018/07/19 全球购物
成人高等教育毕业生自我鉴定
2013/10/22 职场文书
通信工程毕业生求职信
2013/11/16 职场文书
大学生简历的个人自我评价
2013/12/04 职场文书
春节联欢晚会主持词范文
2014/03/24 职场文书
办公室禁烟通知
2015/04/23 职场文书
2015年社区工会工作总结
2015/05/26 职场文书
职工培训工作总结
2015/08/10 职场文书