优化使用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 array_walk() 数组函数
Jul 12 PHP
基于php和mysql的简单的dao类实现crud操作功能
Jan 27 PHP
CI框架在CLI下执行占用内存过大问题的解决方法
Jun 17 PHP
php的mssql数据库连接类实例
Nov 28 PHP
PHP实现股票趋势图和柱形图
Feb 07 PHP
PHP 反射(Reflection)使用实例
May 12 PHP
浅谈php中include文件变量作用域
Jun 18 PHP
PHP合并discuz用户脚本的方法
Aug 04 PHP
PHP邮件群发机实现代码
Feb 16 PHP
yum命令安装php7和相关扩展
Jul 04 PHP
Laravel5中防止XSS跨站攻击的方法
Oct 10 PHP
Laravel框架模板加载,分配变量及简单路由功能示例
Jun 11 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数组去重的函数代码
2013/02/03 PHP
PHP框架Laravel插件Pagination实现自定义分页
2020/04/22 PHP
swoole_process实现进程池的方法示例
2018/10/29 PHP
了解Javascript的模块化开发
2015/03/02 Javascript
JQuery EasyUI的使用
2016/02/24 Javascript
谈一谈jQuery核心架构设计
2016/03/28 Javascript
Angular.js回顾ng-app和ng-model使用技巧
2016/04/26 Javascript
关于javascript原型的修改与重写(覆盖)差别详解
2016/08/31 Javascript
layer弹出层框架alert与msg详解
2017/03/14 Javascript
vue调用高德地图实例代码
2017/04/28 Javascript
用p5.js制作烟花特效的示例代码
2018/03/21 Javascript
详解vue2.0监听属性的使用心得及搭配计算属性的使用
2018/07/18 Javascript
Vue中 axios delete请求参数操作
2020/08/25 Javascript
解决vscode进行vue格式化,会自动补分号和双引号的问题
2020/10/26 Javascript
解决antd 表单设置默认值initialValue后验证失效的问题
2020/11/02 Javascript
Python中的变量和作用域详解
2016/07/13 Python
python正则表达式re之compile函数解析
2017/10/25 Python
Python管理Windows服务小脚本
2018/03/12 Python
TensorFlow实现iris数据集线性回归
2018/09/07 Python
python打包生成的exe文件运行时提示缺少模块的解决方法
2018/10/31 Python
python执行CMD指令,并获取返回的方法
2018/12/19 Python
Python队列RabbitMQ 使用方法实例记录
2019/08/05 Python
Python实现使用dir获取类的方法列表
2019/12/24 Python
Python %r和%s区别代码实例解析
2020/04/03 Python
通过代码实例解析Pytest运行流程
2020/08/20 Python
python3:excel操作之读取数据并返回字典 + 写入的案例
2020/09/01 Python
Python中使用Selenium环境安装的方法步骤
2021/02/22 Python
英国豪华针织品牌John Smedley的在线销售商:The Outlet by John Smedley
2018/04/08 全球购物
教师个人鉴定材料
2014/02/08 职场文书
文案策划求职信
2014/04/14 职场文书
实习生评语
2014/04/26 职场文书
专家推荐信模板
2014/05/09 职场文书
英语系毕业生求职信
2014/07/13 职场文书
班级元旦晚会开幕词
2016/03/04 职场文书
导游词之四川武侯祠
2019/10/21 职场文书
Win11 22H2 2022怎么更新? 获得Win1122H22022版本升级技巧
2022/09/23 数码科技