将PHP的session数据存储到数据库中的代码实例


Posted in PHP onJune 24, 2016

一个开发环境有多个网站,需要使用不同的session,解决方案很多。不过这次也高大上一把,用数据库存,方便以后扩展。

PostgreSQL版
首先是数据库的部分

--drop table php_session
create unlogged table php_session
(
  sess_id varchar(32) primary key,
  modify_time timestamp with time zone not null,
  sess_data varchar(3000) default ''
);

create index concurrently idx_php_session_modify_time on php_session(modify_time);

--set_session(id, data)
create or replace function set_session(varchar, varchar) returns void as $set_session$
  with upsert as (
    update php_session
    set modify_time = current_timestamp, sess_data = $2
    where sess_id = $1
    returning 1
  )
  insert into php_session (sess_id, modify_time, sess_data)
  select $1, current_timestamp, $2
  where not exists (
    select 1 from upsert
  );
$set_session$ language sql;

--get_session(id)
create or replace function get_session(varchar) returns varchar as $get_session$
  select sess_data from php_session where sess_id = $1
$get_session$ language sql;

--del_session
create or replace function del_session(varchar) returns void as $del_session$
  delete from php_session where sess_id = $1
$del_session$ language sql;

--gc_session
create or replace function gc_session() returns void as $del_session$
  delete from php_session where modify_time < current_timestamp - interval '30 days'
$del_session$ language sql;

然后是PHP的部分

<?php

session_set_save_handler(
  function ($savePath, $sessionName) {//open
    return true;
  },
  function () {//close
    return true;
  },
  function ($id) {//read
    $sql = "select get_session($1)";
    $stmt = pg_query_params(SESSION_CONN, $sql, array($id));
    $result = pg_fetch_row($stmt);
    
    return $result[0];
  },
  function ($id, $data) {//write
    $sql = "select set_session($1, $2)";
    pg_query_params(SESSION_CONN, $sql, array($id, $data));
    return true;
  },
  function ($id) {//destroy
    $sql = "select del_session($1)";
    pg_query_params(SESSION_CONN, $sql, array($id, $data));
    return true;
  },
  function ($maxlifetime) {//gc
    //php needn't control the global session gc 
    return true;
  }
);

register_shutdown_function('session_write_close');

?>

然后只要在session_start之前调用这个就可以了

至于SESSION_CONN,那是我定义的一个常量,表示一个指向session数据库的链接而已。

MySQL版
再总结一个针对MySQL的集成更多基础功能的例子:
表结构:

CREATE TABLE IF NOT EXISTS `sessioninfo` (
 `sid` varchar(255) NOT NULL,
 `value` text NOT NULL,
 `expiration` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 PRIMARY KEY (`sid`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

session信息存储到数据库的类:

class MySessionHandler implements SessionHandlerInterface {
 
  /**
  * @access private
  * @var object 数据库连接
  */
  private $_dbLink;
  /**
  * @access private
  * @var string 保存session的表名
  */
  Private $_sessionTable;
  /**
  * @access private
  * @var string session名
  */
  private $_sessionName;
  /**
  * @const 过期时间
  */
  const SESSION_EXPIRE = 10;
 
  public function __construct($dbLink, $sessionTable) {
    if(!is_object($dbLink)) {
      return false;
    }
    $this->_dbLink = $dbLink;
    $this->_sessionTable = $sessionTable;
  }
 
  /**
  * 打开
  * @access public
  * @param string $session_save_path 保存session的路径
  * @param string $session_name session名
  * @return integer
  */
  public function open($session_save_path, $session_name) {
    $this->_sessionName = $session_name;
    return 0;
  }
 
  /**
  * 关闭
  * @access public
  * @return integer
  */
  public function close() {
    return 0;
  }
 
  /**
  * 关闭session
  * @access public
  * @param string $session_id session ID
  * @return string
  */
  public function read($session_id) {
    $query = "SELECT value FROM {$this->_sessionTable} WHERE sid = {$session_id} AND UNIX_TIMESTAMP(expiration) + " . self::SESSION_EXPIRE . " > UNIX_TIMESTAMP(NOW())";
    $result = $this->_dbLink->query($query);
    if(!isset($value) || empty($value)) {
      $value = "";
      return $value;
    }
    $this->_dbLink->query("UPDATE {$this->_sessionTable} SET expiration = CURRENT_TIMESTAMP() WHERE sid = {$session_id}");
    $value = $result->fetch_array();
    $result->free();
    return $value['value'];
  }
 
  /**
  * 写入session
  * @access public
  * @param string $session_id session ID
  * @param string $session_data session data
  * @return integer
  */
  public function write($session_id, $session_data) {
    $query = "SELECT value FROM {$this->_sessionTable} WHERE sid = '{$session_id}' AND UNIX_TIMESTAMP(expiration) + " . self::SESSION_EXPIRE . " > UNIX_TIMESTAMP(NOW())";
    $result = $this->_dbLink->query($query);
    $result = $result->fetch_array();
    if(!empty($result)) {
      $result = $this->_dbLink->query("UPDATE {$this->_sessionTable} SET value = {$session_data} WHERE sid = {$session_id}");
    }
    else{
      $result = $this->_dbLink->query("INSERT INTO {$this->_sessionTable} (sid, value) VALUES ('{$session_id}', '{$session_data}')");
    }
    if($result){
      return 0;
    }
    else{
      return 1;
    }    
  }
 
  /**
  * 销魂session
  * @access public
  * @param string $session_id session ID
  * @return integer
  */
  public function destroy($session_id) {
    $result = $this->_dbLink->query("DELETE FROM {$this->_sessionTable} WHERE sid = '{$session_id}'");
    if($result){
      return 0;
    }
    else{
      return 1;
    }
  }
 
  /**
  * 垃圾回收
  * @access public
  * @param string $maxlifetime session 最长生存时间
  * @return integer
  */
  public function gc($maxlifetime) {
    $result = $this->_dbLink->query("DELETE FROM {$this->_sessionTable} WHERE UNIX_TIMESTAMP(expiration) < UNIX_TIMESTAMP(NOW()) - " . self::SESSION_EXPIRE);
    if($result){
      return 0;
    }
    else{
      return 1;
    }
  }
 
}





$dbLink = new mysqli("localhost", "root", "root", "test");
$sessionTable = "sessioninfo";
 
$handler = new MySessionHandler($dbLink, $sessionTable);
session_set_save_handler($handler);
session_start();
$_SESSION['name'] = "test";
echo $_SESSION["name"];
//session_destroy();
PHP 相关文章推荐
PHP与已存在的Java应用程序集成
Oct 09 PHP
用PHP编写PDF文档生成器
Oct 09 PHP
实现了一个PHP5的getter/setter基类的代码
Feb 25 PHP
smarty模板局部缓存方法使用示例
Jun 17 PHP
非常实用的PHP常用函数汇总
Dec 17 PHP
Laravel 5框架学习之向视图传送数据(进阶篇)
Apr 08 PHP
PHP SPL标准库之SplFixedArray使用实例
May 12 PHP
Yii中srbac权限扩展模块工作原理与用法分析
Jul 14 PHP
PHP读取word文档的方法分析【基于COM组件】
Aug 01 PHP
thinkPHP框架动态配置用法实例分析
Jun 14 PHP
基于PHP实现用户登录注册功能的详细教程
Aug 04 PHP
50个优秀经典PHP算法大集合 附源码
Aug 26 PHP
php自动载入类用法实例分析
Jun 24 #PHP
php模拟post上传图片实现代码
Jun 24 #PHP
一个简单安全的PHP验证码类 附调用方法
Jun 24 #PHP
java微信开发之上传下载多媒体文件
Jun 24 #PHP
微信公众号判断用户是否已关注php代码解析
Jun 24 #PHP
php微信开发之上传临时素材
Jun 24 #PHP
PHP微信开发之模板消息回复
Jun 24 #PHP
You might like
php开发环境配置记录
2011/01/14 PHP
php计算两个整数的最大公约数常用算法小结
2015/03/05 PHP
帝国cms常用标签汇总
2015/07/06 PHP
laravel自定义分页效果
2017/07/23 PHP
php注册系统和使用Xajax即时验证用户名是否被占用
2017/08/31 PHP
PHP实现压缩图片尺寸并转为jpg格式的方法示例
2018/05/10 PHP
jquery获取URL中参数解决中文乱码问题的两种方法
2013/12/18 Javascript
利用javascript判断文件是否存在
2013/12/31 Javascript
jQuery中die()方法用法实例
2015/01/19 Javascript
根据Bootstrap Paginator改写的js分页插件
2016/12/25 Javascript
JavaScript实现左右下拉框动态增删示例
2017/03/09 Javascript
vue中的$emit 与$on父子组件与兄弟组件的之间通信方式
2018/05/13 Javascript
JavaScript的变量声明与声明提前用法实例分析
2019/11/26 Javascript
[03:05]《我与DAC》之xiao8:DAC与BG
2018/03/27 DOTA
[01:38]完美世界高校联赛决赛花絮
2018/12/02 DOTA
python anaconda 安装 环境变量 升级 以及特殊库安装的方法
2017/06/21 Python
手把手教你python实现SVM算法
2017/12/27 Python
Python基础教程之利用期物处理并发
2018/03/29 Python
示例详解Python3 or Python2 两者之间的差异
2018/08/23 Python
python实现最大子序和(分治+动态规划)
2019/07/05 Python
python之拟合的实现
2019/07/19 Python
python实现发送form-data数据的方法详解
2019/09/27 Python
Python类的绑定方法和非绑定方法实例解析
2020/03/04 Python
Python基于codecs模块实现文件读写案例解析
2020/05/11 Python
python退出循环的方法
2020/06/18 Python
Python实现PS滤镜中的USM锐化效果
2020/12/04 Python
html5 Canvas画图教程(5)—canvas里画曲线之arc方法
2013/01/09 HTML / CSS
html5中canvas图表实现柱状图的示例
2017/11/13 HTML / CSS
英国户外玩具儿童游乐设备网站:TP Toys(蹦床、攀爬框架、秋千、滑梯和游戏屋)
2018/04/09 全球购物
下面代码从性能上考虑,有什么问题
2015/04/03 面试题
教师岗位职责
2013/11/17 职场文书
策划助理岗位职责
2013/11/18 职场文书
高中学生评语大全
2014/04/25 职场文书
2015庆祝七一建党节94周年活动总结
2015/03/20 职场文书
机器人瓦力观后感
2015/06/12 职场文书
教师研修随笔感言
2015/11/18 职场文书