优化使用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方法调用模式与函数调用模式简例
Sep 20 PHP
PHP与MYSQL中UTF8 中文排序示例代码
Oct 23 PHP
浅谈php正则表达式中的非贪婪模式匹配的使用
Nov 25 PHP
ThinkPHP进程计数类Process用法实例详解
Sep 25 PHP
WordPres对前端页面调试时的两个PHP函数使用小技巧
Dec 22 PHP
PHP常见漏洞攻击分析
Feb 21 PHP
php、java、android、ios通用的3des方法(推荐)
Sep 09 PHP
yii2利用自带UploadedFile实现上传图片的示例
Feb 16 PHP
Laravel实现autoload方法详解
May 07 PHP
PHP 实现从数据库导出到.csv文件方法
Jul 06 PHP
对于Laravel 5.5核心架构的深入理解
Feb 22 PHP
基于PHP实现堆排序原理及实例详解
Jun 19 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实现自动补全功能源码
2013/05/15 PHP
Yii基于数组和对象的Model查询技巧实例详解
2015/12/28 PHP
PHP检测用户是否关闭浏览器的方法
2016/02/14 PHP
给moz-firefox下添加IE方法和属性
2007/04/10 Javascript
Aptana调试javascript图解教程
2009/11/30 Javascript
JavaScript 存在陷阱 删除某一区域所有节点
2010/05/10 Javascript
几种延迟加载JS代码的方法加快网页的访问速度
2013/10/12 Javascript
在JavaScript中操作数组之map()方法的使用
2015/06/09 Javascript
JS实现选择TextArea内文本的方法
2015/08/03 Javascript
JavaScript判断微信浏览器实例代码
2016/06/13 Javascript
AngularJS 视图详解及示例代码
2016/08/17 Javascript
教你快速搭建Node.Js服务器的方法教程
2017/03/30 Javascript
详解用webpack把我们的业务模块分开打包的方法
2017/07/20 Javascript
使用react-router4.0实现重定向和404功能的方法
2017/08/28 Javascript
react 父子组件之间通讯props
2018/09/08 Javascript
vue 对axios get pust put delete封装的实例代码
2020/01/05 Javascript
vue实现放大镜效果
2020/09/17 Javascript
python控制台显示时钟的示例
2014/02/24 Python
Python实现计算文件夹下.h和.cpp文件的总行数
2015/04/23 Python
Python实现一个简单的验证码程序
2017/11/03 Python
python按行读取文件,去掉每行的换行符\n的实例
2018/04/19 Python
浅析Python与Mongodb数据库之间的操作方法
2019/07/01 Python
Python:type、object、class与内置类型实例
2019/12/25 Python
Python3基本输入与输出操作实例分析
2020/02/14 Python
微软中国官方商城:Microsoft Store中国
2018/10/12 全球购物
Hush Puppies澳大利亚官网:舒适的男女休闲和正装鞋
2019/08/24 全球购物
C和C++经典笔试题附答案解析
2014/08/18 面试题
仓库保管员岗位职责
2013/12/20 职场文书
学生打架检讨书1000字
2014/01/16 职场文书
留学推荐信怎么写
2014/01/25 职场文书
工地宣传标语
2014/06/18 职场文书
物理课外活动总结
2014/08/27 职场文书
个人典型事迹材料
2014/12/30 职场文书
大学生暑假实习总结
2015/07/13 职场文书
python process模块的使用简介
2021/05/14 Python
laravel添加角色和模糊搜索功能的实现代码
2021/06/22 PHP