优化使用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 相关文章推荐
session 的生命周期是多长
Oct 09 PHP
PHP的栏目导航程序
Oct 09 PHP
简单的php 验证图片生成函数
May 21 PHP
使用PHP计算两个路径的相对路径
Jun 14 PHP
php防注入及开发安全详细解析
Aug 09 PHP
php 判断网页是否是utf8编码的方法
Jun 06 PHP
解密ThinkPHP3.1.2版本之模块和操作映射
Jun 19 PHP
php生成酷炫的四个字符验证码
Apr 22 PHP
php array_merge_recursive 数组合并
Oct 26 PHP
解决laravel 5.1报错:No supported encrypter found的办法
Jun 07 PHP
phpQuery采集网页实现代码实例
Apr 02 PHP
php设计模式之备忘模式分析【星际争霸游戏案例】
Mar 24 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
11个PHP 分页脚本推荐
2011/08/15 PHP
迅速确定php多维数组的深度的方法
2014/01/07 PHP
CodeIgniter多语言实现方法详解
2016/01/20 PHP
PHP截取IE浏览器并缩小原图的方法
2016/03/04 PHP
php微信公众账号开发之前五个坑(一)
2016/09/18 PHP
jquery+thinkphp实现跨域抓取数据的方法
2016/10/15 PHP
PHP给前端返回一个JSON对象的实例讲解
2018/05/31 PHP
Jquery easyui 下loaing效果示例代码
2013/08/12 Javascript
一个简单的实现下拉框多选的插件可移植性比较好
2014/05/05 Javascript
jQuery学习笔记之jQuery.fn.init()的参数分析
2014/06/09 Javascript
javascript制作的cookie封装及使用指南
2015/01/02 Javascript
JavaScript中property和attribute的区别详细介绍
2015/03/03 Javascript
jQuery实现文件上传进度条特效
2015/08/12 Javascript
jQuery模仿京东/天猫商品左侧分类导航菜单效果
2016/06/29 Javascript
基于JS实现类似支付宝支付密码输入框
2016/09/02 Javascript
Vue导出json数据到Excel电子表格的示例
2017/12/04 Javascript
vue中使用ueditor富文本编辑器
2018/02/08 Javascript
vue模式history下在iis中配置流程
2019/04/17 Javascript
ES11新增的这9个新特性,你都掌握了吗
2020/10/15 Javascript
Python中返回字典键的值的values()方法使用
2015/05/22 Python
python图像处理之反色实现方法
2015/05/30 Python
浅谈Python peewee 使用经验
2017/10/20 Python
Python 中的Selenium异常处理实例代码
2018/05/03 Python
python实现感知器算法(批处理)
2019/01/18 Python
Python dict和defaultdict使用实例解析
2020/03/12 Python
如何基于python实现不邻接植花
2020/05/01 Python
python opencv 实现读取、显示、写入图像的方法
2020/06/08 Python
python 5个顶级异步框架推荐
2020/09/09 Python
YSL Beauty加拿大官方商城:圣罗兰美妆加拿大
2017/05/15 全球购物
小女主人连衣裙:Little Mistress
2017/07/10 全球购物
农民入党思想汇报
2014/01/03 职场文书
党员入党表决心的话
2014/03/11 职场文书
2014年教研活动总结范文
2014/04/26 职场文书
2015年敬老院工作总结
2015/05/18 职场文书
天堂的孩子观后感
2015/06/11 职场文书
教你使用Pandas直接核算Excel中快递费用
2021/05/12 Python