优化使用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 中的一些经验积累
Oct 09 PHP
php session 预定义数组
Mar 16 PHP
php操作SVN版本服务器类代码
Nov 27 PHP
php中长文章分页显示实现代码
Sep 29 PHP
php解析json数据实例
Aug 19 PHP
php常见的魔术方法详解
Dec 25 PHP
解决phpcms更换javascript的幻灯片代码调用图片问题
Dec 26 PHP
PHP函数extension_loaded()用法实例
Jan 19 PHP
PHP创建文件,并向文件中写入数据,覆盖,追加的实现代码
Mar 25 PHP
Yii2框架RESTful API 格式化响应,授权认证和速率限制三部分详解
Nov 10 PHP
php接口技术实例详解
Dec 07 PHP
ThinkPHP3.1.2 使用cli命令行模式运行的方法
Apr 14 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_fetch_assoc返回来的数组 不用foreach----echo
2011/05/04 PHP
PHP中定义数组常量(array常量)的方法
2014/11/17 PHP
Thinkphp框架 表单自动验证登录注册 ajax自动验证登录注册
2016/12/27 PHP
php 实现银联商务H5支付的示例代码
2019/10/12 PHP
javascript mouseover、mouseout停止事件冒泡的解决方案
2009/04/07 Javascript
javascript 全选与全取消功能的实现代码
2012/12/23 Javascript
jQuery中 noConflict() 方法使用
2013/04/25 Javascript
浅谈JavaScript中的Math.atan()方法的使用
2015/06/14 Javascript
js 中获取制定的cook信息实现方法
2016/11/19 Javascript
JavaScript模块模式实例详解
2017/10/25 Javascript
bootstrap paginator分页插件的两种使用方式实例详解
2017/11/14 Javascript
Vue官网todoMVC示例代码
2018/01/29 Javascript
微信小程序将字符串生成二维码图片的操作方法
2018/07/17 Javascript
读懂CommonJS的模块加载
2019/04/19 Javascript
Vue实现简单计算器案例
2020/02/25 Javascript
使用Python的Tornado框架实现一个简单的WebQQ机器人
2015/04/24 Python
TF-IDF算法解析与Python实现方法详解
2017/11/16 Python
matplotlib在python上绘制3D散点图实例详解
2017/12/09 Python
python处理csv中的空值方法
2018/06/22 Python
python twilio模块实现发送手机短信功能
2019/08/02 Python
python聚类算法解决方案(rest接口/mpp数据库/json数据/下载图片及数据)
2019/08/28 Python
Python爬取酷狗MP3音频的步骤
2021/02/26 Python
HTML5手指下滑弹出负一屏阻止移动端浏览器内置下拉刷新功能的实现代码
2020/04/10 HTML / CSS
新娘父亲婚礼致辞
2014/01/16 职场文书
荷叶圆圆教学反思
2014/02/01 职场文书
竞聘上岗演讲稿
2014/05/16 职场文书
党员干部群众路线个人整改措施
2014/09/18 职场文书
个人买房协议书范本
2014/10/06 职场文书
秦兵马俑导游词
2015/02/02 职场文书
《叶问2》观后感
2015/06/15 职场文书
工作感言一句话
2015/08/01 职场文书
班主任远程培训研修日志
2015/11/13 职场文书
2016年度先进班组事迹材料
2016/03/01 职场文书
redis cluster支持pipeline的实现思路
2021/06/23 Redis
德生TECSUN S-2000使用手册文字版
2022/05/10 无线电
在Oracle表中进行关键词搜索的过程
2022/06/10 Oracle