优化使用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配置心得包含MYSQL5乱码解决
Nov 20 PHP
9个PHP开发常用功能函数小结
Jul 15 PHP
php 文章调用类代码
Aug 11 PHP
几种有用的变型 PHP中循环语句的用法介绍
Jan 30 PHP
Windows和Linux中php代码调试工具Xdebug的安装与配置详解
May 08 PHP
ThinkPHP中URL路径访问与模块控制器之间的关系
Aug 23 PHP
浅析PHP中strlen和mb_strlen的区别
Aug 31 PHP
浅析php原型模式
Nov 25 PHP
php生成html文件方法总结
Dec 01 PHP
PHP多态代码实例
Jun 26 PHP
浅谈Yii乐观锁的使用及原理
Jul 25 PHP
PHP后门隐藏的一些技巧总结
Nov 04 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 jquery 实现新闻标签分类与无刷新分页
2009/12/18 PHP
php curl常见错误:SSL错误、bool(false)
2011/12/28 PHP
php在项目中寻找代码的坏味道(综艺命名)
2012/07/19 PHP
PHP获取当前url的具体方法全面解析
2013/11/26 PHP
PHP中把有符号整型转换为无符号整型方法
2015/05/27 PHP
PHP+redis实现添加处理投票的方法
2015/11/14 PHP
PHP生成推广海报的方法分享
2018/04/22 PHP
不常用但很实用的PHP预定义变量分析
2019/06/25 PHP
一段非常简单的让图片自动切换js代码
2006/11/10 Javascript
跟着Jquery API学Jquery之一 选择器
2010/04/07 Javascript
js 页面关闭前的出现提示的实现代码
2011/05/25 Javascript
Raphael带文本标签可拖动的图形实现代码
2013/02/20 Javascript
js实现数组去重、判断数组以及对象中的内容是否相同
2013/11/29 Javascript
jquery插件unobtrusive实现片段式加载
2015/06/15 Javascript
JS Ajax请求如何防止重复提交
2016/06/13 Javascript
jQuery Validate插件实现表单验证
2016/08/19 Javascript
node.js实现复制文本到剪切板的功能
2017/01/23 Javascript
JavaScript实现省市联动过程中bug的解决方法
2017/12/04 Javascript
微信小程序用户位置权限的获取方法(拒绝后提醒)
2018/11/15 Javascript
javascriptvoid(0)含义以及与&quot;#&quot;的区别讲解
2019/01/19 Javascript
ES6扩展运算符和rest运算符用法实例分析
2020/05/23 Javascript
[58:32]EG vs Liquid 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
python通过pil模块将raw图片转换成png图片的方法
2015/03/16 Python
操作Windows注册表的简单的Python程序制作教程
2015/04/07 Python
python pytest进阶之fixture详解
2019/06/27 Python
Python3 字典dictionary入门基础附实例
2020/02/10 Python
python opencv 检测移动物体并截图保存实例
2020/03/10 Python
python中用ggplot绘制画图实例讲解
2021/01/26 Python
Hashtable 添加内容的方式有哪几种,有什么区别?
2012/04/08 面试题
北京麒麟网信息技术有限公司网络游戏测试面试题
2013/09/28 面试题
学生会竞选演讲稿怎么写
2014/08/26 职场文书
三八节祝酒词
2015/08/11 职场文书
2016年“我们的节日·重阳节”主题活动总结
2016/04/01 职场文书
python 通过使用Yolact训练数据集
2021/04/06 Python
MySQL 存储过程的优缺点分析
2021/05/20 MySQL
万能密码的SQL注入漏洞其PHP环境搭建及防御手段
2021/09/04 SQL Server