优化使用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新手谈谈我的学习心得
Feb 25 PHP
php导出word格式数据的代码实例
Nov 25 PHP
ThinkPHP应用模式扩展详解
Jul 16 PHP
smarty模板引擎从php中获取数据的方法
Jan 22 PHP
PHP输出多个元素的排列或组合的方法
Mar 14 PHP
[原创]php使用strpos判断字符串中数字类型子字符串出错的解决方法
Apr 01 PHP
PHP实现防盗链的方法分析
Jul 25 PHP
php格式文件打开的四种方法
Feb 24 PHP
PHP实现的超长文本分页显示功能示例
Jun 04 PHP
Laravel 实现Controller向blade前台模板赋值的四种方式小结
Oct 22 PHP
php实现断点续传大文件示例代码
Jun 19 PHP
PHP 实现重载
Mar 09 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+mysql开源XNA 聚合程序发布 下载
2007/07/13 PHP
使用php+apc实现上传进度条且在IE7下不显示的问题解决方法
2013/04/25 PHP
腾讯QQ微博API接口获取微博内容
2013/10/30 PHP
PHP检测字符串是否为UTF8编码的常用方法
2014/11/21 PHP
JavaScript 学习笔记 Black.Caffeine 09.11.28
2009/11/30 Javascript
一个基于jquery的图片切换效果
2010/07/06 Javascript
js遍历子节点子元素附属性及方法
2014/08/19 Javascript
JavaScript中的对象的extensible属性介绍
2014/12/30 Javascript
JavaScript实现自动对页面上敏感词进行屏蔽的方法
2015/07/27 Javascript
jquery实现顶部向右伸缩的导航区域代码
2015/09/02 Javascript
详解 javascript中offsetleft属性的用法
2015/11/11 Javascript
JavaScript 输出显示内容(document.write、alert、innerHTML、console.log)
2016/12/14 Javascript
JavaScript实现简单的四则运算计算器完整实例
2017/04/28 Javascript
vue2.0 常用的 UI 库实例讲解
2017/12/12 Javascript
Vue-cli Eslint在vscode里代码自动格式化的方法
2018/02/23 Javascript
vue写h5页面的方法总结
2019/02/12 Javascript
解决vue中使用proxy配置不同端口和ip接口问题
2019/08/14 Javascript
VueCli生产环境打包部署跨域失败的解决
2020/11/13 Javascript
Python 备份程序代码实现
2017/03/06 Python
Python实现的本地文件搜索功能示例【测试可用】
2018/05/30 Python
python中pip的安装与使用教程
2018/08/10 Python
python 制作自定义包并安装到系统目录的方法
2018/10/27 Python
基于OpenCV python3实现证件照换背景的方法
2019/03/22 Python
PyQt5-QDateEdit的简单使用操作
2020/07/12 Python
css3实现二维码扫描特效的示例
2020/10/29 HTML / CSS
Perfumetrader荷兰:香水、化妆品和护肤品在线商店
2017/09/15 全球购物
GUESS Factory加拿大:牛仔裤、服装及配饰
2019/09/20 全球购物
Clarks鞋澳大利亚官方网站:Clarks Australia
2019/12/25 全球购物
主持人婚宴答谢词
2014/01/28 职场文书
竞选班干部演讲稿
2014/04/24 职场文书
民政局副局长民主生活会个人整改措施
2014/10/04 职场文书
小学运动会宣传稿
2015/07/23 职场文书
文艺部部长竞选稿
2015/11/21 职场文书
Nginx域名转发https访问的实现
2021/03/31 Servers
Python获取指定日期是"星期几"的6种方法
2022/03/13 Python
css如何把元素固定在容器底部的四种方式
2022/06/16 HTML / CSS