将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 相关文章推荐
一个SQL管理员的web接口
Oct 09 PHP
php中使用Curl、socket、file_get_contents三种方法POST提交数据
Aug 12 PHP
php中3des加密代码(完全与.net中的兼容)
Aug 02 PHP
浅谈apache和nginx的rewrite的区别
Feb 22 PHP
判断php数组是否为索引数组的实现方法
Jun 13 PHP
分割GBK中文遭遇乱码的解决方法
Aug 09 PHP
PHP 实现类似js中alert() 提示框
Mar 18 PHP
PHP判断FORM表单或URL参数来的数据是否为整数的方法
Mar 25 PHP
PHP函数import_request_variables()用法分析
Apr 02 PHP
浅谈PHP eval()函数定义和用法
Jun 21 PHP
php成功操作redis cluster集群的实例教程
Jan 13 PHP
PHP实现递归的三种方法
Jul 04 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
利用curl抓取远程页面内容的示例代码
2013/07/23 PHP
PHP中的多行字符串传递给JavaScript的两种方法
2014/06/19 PHP
PHP中的魔术方法总结和使用实例
2015/05/11 PHP
PHP实现多维数组转字符串和多维数组转一维数组的方法
2015/08/08 PHP
日常整理PHP中简单的图形处理(经典)
2015/10/26 PHP
PHP中substr_count()函数获取子字符串出现次数的方法
2016/01/07 PHP
Symfony模板的快捷变量用法实例
2016/03/17 PHP
struts2+jquery组合验证注册用户是否存在
2014/04/30 Javascript
JavaScript设计模式之单件模式介绍
2014/12/28 Javascript
javascript动态设置样式style实例分析
2015/05/13 Javascript
Jquery+Ajax+PHP+MySQL实现分类列表管理(上)
2015/10/28 Javascript
jQuery实现的导航动画效果(附demo源码)
2016/04/01 Javascript
Vue.js常用指令汇总(v-if、v-for等)
2016/11/03 Javascript
jquery.tableSort.js表格排序插件使用方法详解
2020/08/12 Javascript
vue.js异步上传文件前后端实现代码
2017/08/22 Javascript
浅析前端路由简介以及vue-router实现原理
2018/06/01 Javascript
JS html事件冒泡和事件捕获操作示例
2019/05/01 Javascript
详解VSCode配置启动Vue项目
2019/05/14 Javascript
小程序跳转H5页面的方法步骤
2020/03/06 Javascript
Jquery 获取相同NAME 或者id删除行操作
2020/08/24 jQuery
原生微信小程序开发中 redux 的使用详解
2021/02/18 Javascript
Python简单实现两个任意字符串乘积的方法示例
2018/04/12 Python
python利用smtplib实现QQ邮箱发送邮件
2020/05/20 Python
Python实现的tcp端口检测操作示例
2018/07/24 Python
实例讲解python中的协程
2018/10/08 Python
python 文本单词提取和词频统计的实例
2018/12/22 Python
python的sorted用法详解
2019/06/25 Python
python 叠加等边三角形的绘制的实现
2019/08/14 Python
简约控的天堂:The Undone
2016/12/21 全球购物
荷兰在线啤酒店:Beerwulf
2019/08/26 全球购物
哥德堡通行证:Gothenburg Pass
2019/12/09 全球购物
后勤人员自我评价怎么写
2013/09/19 职场文书
工程概预算专业毕业生求职信
2013/10/04 职场文书
公开致歉信
2019/06/24 职场文书
一篇文章带你了解Python和Java的正则表达式对比
2021/09/15 Python
详解redis在微服务领域的贡献
2021/10/16 Redis