优化使用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 相关文章推荐
windows xp下安装pear
Dec 02 PHP
PHP字符串的递增和递减示例介绍
Feb 11 PHP
ThinkPHP之getField详解
Jun 20 PHP
php+mysql不用递归实现的无限级分类实例(非递归)
Jul 08 PHP
PHP使用header()输出图片缓存实例
Dec 09 PHP
php在linux下检测mysql同步状态的方法
Jan 15 PHP
PHP 读取大文件并显示的简单实例(推荐)
Aug 12 PHP
php实现等比例不失真缩放上传图片的方法
Nov 14 PHP
PHP实现的文件上传类与用法详解
Jul 05 PHP
PHP基于回溯算法解决n皇后问题的方法示例
Nov 07 PHP
php模拟实现斗地主发牌
Apr 22 PHP
thinkphp 获取控制器及控制器方法
Apr 16 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调用Twitter的RSS的实现代码
2010/03/10 PHP
php skymvc 一款轻量、简单的php
2011/06/28 PHP
学习php设计模式 php实现模板方法模式
2015/12/08 PHP
PHP调试的强悍利器之PHPDBG
2016/02/22 PHP
PHP+Ajax无刷新带进度条图片上传示例
2017/02/08 PHP
JavaScript Timer实现代码
2010/02/17 Javascript
javascript权威指南 学习笔记之变量作用域分享
2011/09/28 Javascript
JavaScript定义类的几种方式总结
2014/01/06 Javascript
Jquery的Tabs内容轮换效果实现代码,几行搞定
2014/02/12 Javascript
邮箱下拉自动填充选择示例代码附图
2014/04/03 Javascript
JavaScript实现非常简单实用的下拉菜单效果
2015/08/27 Javascript
JavaScript 拖拽实例代码
2016/09/21 Javascript
JS仿京东移动端手指拨动切换轮播图效果
2020/04/10 Javascript
JavaScript运动框架 多物体任意值运动(三)
2017/05/17 Javascript
详解用vue.js和laravel实现微信授权登陆
2017/06/23 Javascript
Vue EventBus自定义组件事件传递
2018/06/25 Javascript
layDate插件设置开始和结束时间
2018/11/15 Javascript
微信小程序和H5页面间相互跳转代码实例
2019/09/19 Javascript
Vue实现简单的拖拽效果
2020/08/25 Javascript
Python使用ntplib库同步校准当地时间的方法
2016/07/02 Python
Python 中 Virtualenv 和 pip 的简单用法详解
2017/08/18 Python
python微信公众号之关键词自动回复
2018/06/15 Python
Python中psutil的介绍与用法
2019/05/02 Python
python读取多层嵌套文件夹中的文件实例
2020/02/27 Python
Python Pillow(PIL)库的用法详解
2020/09/19 Python
Python中过滤字符串列表的方法
2020/12/22 Python
美国运动鞋类和服装零售连锁店:Shoe Palace
2019/08/13 全球购物
俄罗斯香水在线商店:AromaCode
2019/12/04 全球购物
什么是重载?CTS、CLS和CLR分别做何解释
2012/05/06 面试题
高分子材料个人求职信范文
2013/09/25 职场文书
员工团队活动方案
2014/08/28 职场文书
2014年后勤管理工作总结
2014/12/01 职场文书
教师工作能力自我评价
2015/03/04 职场文书
2015暑期社会实践调查报告
2015/07/14 职场文书
分布式架构Redis中有哪些数据结构及底层实现原理
2022/03/13 Redis
Windows10安装Apache2.4的方法步骤
2022/06/25 Servers