将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数据库连接
Oct 09 PHP
PHP正则的Unknown Modifier错误解决方法
Mar 02 PHP
php绝对路径与相对路径之间关系的的分析
Mar 03 PHP
PHP弹出提示框并跳转到新页面即重定向到新页面
Jan 24 PHP
php中session使用示例
Mar 29 PHP
PHP扩展CURL的用法详解
Jun 20 PHP
php常用的url处理函数总结
Nov 19 PHP
win平台安装配置Nginx+php+mysql 环境
Jan 12 PHP
PHP正则+Snoopy抓取框架实现的抓取淘宝店信誉功能实例
May 17 PHP
Yii2中简单的场景使用介绍
Jun 02 PHP
PHP并发查询MySQL的实例代码
Aug 09 PHP
阿里云Win2016安装Apache和PHP环境图文教程
Mar 11 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
初探jquery——表单应用范例
2007/02/20 Javascript
Javascript 实用小技巧
2010/04/07 Javascript
用XMLDOM和ADODB.Stream实现base64编码解码实现代码
2010/11/28 Javascript
jQuery使用动态渲染表单功能完成ajax文件下载
2013/01/15 Javascript
Javascript和HTML5利用canvas构建Web五子棋游戏实现算法
2013/07/17 Javascript
JS的千分位算法实现思路
2013/07/31 Javascript
jQuery 绑定事件到动态创建的元素上的方法实例
2013/08/18 Javascript
js创建元素(节点)示例
2014/01/02 Javascript
input:checkbox多选框实现单选效果跟radio一样
2014/06/16 Javascript
JS实现字符串转日期并比较大小实例分析
2015/12/09 Javascript
JS实现iframe编辑器光标位置插入内容的方法(兼容IE和Firefox)
2016/06/24 Javascript
javascript事件的传播基础实例讲解(35)
2017/02/14 Javascript
微信小程序中吸底按钮适配iPhone X方案
2017/11/29 Javascript
动态Axios的配置步骤详解
2018/01/12 Javascript
详解基于DllPlugin和DllReferencePlugin的webpack构建优化
2018/06/28 Javascript
5分钟学会Vue动画效果(小结)
2018/07/21 Javascript
Vue 解决通过this.$refs来获取DOM或者组件报错问题
2020/07/28 Javascript
利用Vue实现简易播放器的完整代码
2020/12/30 Vue.js
[02:36]DOTA2英雄基础教程 帕格纳
2014/01/20 DOTA
Python ORM框架SQLAlchemy学习笔记之安装和简单查询实例
2014/06/10 Python
在Windows8上的搭建Python和Django环境
2014/07/03 Python
Python实现 多进程导入CSV数据到 MySQL
2017/02/26 Python
Python使用回溯法子集树模板获取最长公共子序列(LCS)的方法
2017/09/08 Python
基于Python中capitalize()与title()的区别详解
2017/12/09 Python
深入理解Django的中间件middleware
2018/03/14 Python
Python 调用PIL库失败的解决方法
2019/01/08 Python
在交互式环境中执行Python程序过程详解
2019/07/12 Python
Python+Tensorflow+CNN实现车牌识别的示例代码
2019/10/11 Python
关于Django Models CharField 参数说明
2020/03/31 Python
For Art’s Sake官网:手工制作的奢华眼镜
2018/12/15 全球购物
Club Monaco加拿大官网:设计师男女服装
2019/09/29 全球购物
世界各地的旅游、观光和活动:Isango!
2019/10/29 全球购物
分布式数据库需要考虑哪些问题
2013/12/08 面试题
十岁生日父母答谢词
2014/01/18 职场文书
黄继光的英雄事迹材料
2014/02/13 职场文书
国际经济与贸易专业求职信
2014/07/10 职场文书