优化使用mysql存储session的php代码

  之前写过两篇文章《自定义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);

  }

  }

  ?>

  (注意,该代码不能直接使用,本文主要是提供一种思路)