将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读取IMAP邮件
Oct 09 PHP
php函数array_merge用法一例(合并同类数组)
Feb 03 PHP
PHP文件锁定写入实例解析
Jul 14 PHP
安装ImageMagick出现error while loading shared libraries的解决方法
Sep 23 PHP
php基于双向循环队列实现历史记录的前进后退等功能
Aug 08 PHP
PHP实现JS中escape与unescape的方法
Jul 11 PHP
Thinkphp整合微信支付功能
Dec 14 PHP
总结一些PHP中好用但又容易忽略的小知识
Jun 02 PHP
php获取文章内容第一张图片的方法示例
Jul 03 PHP
PHP静态延迟绑定和普通静态效率的对比
Oct 20 PHP
PHP实现字符串翻转功能的方法【递归与循环算法】
Nov 03 PHP
php和js实现根据子网掩码和ip计算子网功能示例
Nov 09 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
世界收音机发展史
2021/03/01 无线电
file_get_contents获取不到网页内容的解决方法
2013/03/07 PHP
PHP框架Laravel的小技巧两则
2015/02/10 PHP
PHP排序算法类实例
2015/06/17 PHP
全面了解PHP中的全局变量
2016/06/17 PHP
Laravel 修改默认日志文件名称和位置的例子
2019/10/17 PHP
jQuery学习笔记之jQuery的DOM操作
2010/12/22 Javascript
JS修改css样式style浅谈
2013/05/06 Javascript
js使用递归解析xml
2014/12/12 Javascript
javascript操作符&quot;!~&quot;详解
2015/02/10 Javascript
解析Node.js异常处理中domain模块的使用方法
2016/02/16 Javascript
javascript数据类型详解
2017/02/07 Javascript
Angular.JS中的指令引用template与指令当做属性详解
2017/03/30 Javascript
详解webpack的proxyTable无效的解决方案
2018/06/15 Javascript
JavaScript引用类型Function实例详解
2018/08/09 Javascript
从vue源码解析Vue.set()和this.$set()
2018/08/30 Javascript
vue路由--网站导航功能详解
2019/03/29 Javascript
Vue Cli 3项目使用融云IM实现聊天功能的方法
2019/04/19 Javascript
js实现带有动画的返回顶部
2020/08/09 Javascript
openlayers实现图标拖动获取坐标
2020/09/25 Javascript
Python for Informatics 第11章 正则表达式(一)
2016/04/21 Python
使用Python实现windows下的抓包与解析
2018/01/15 Python
Sublime开发python程序的示例代码
2018/01/24 Python
python爬虫URL重试机制的实现方法(python2.7以及python3.5)
2018/12/18 Python
详解Pandas之容易让人混淆的行选择和列选择
2019/07/10 Python
Python 分布式缓存之Reids数据类型操作详解
2020/06/24 Python
详解matplotlib中pyplot和面向对象两种绘图模式之间的关系
2021/01/22 Python
HTML5中form如何关闭自动完成功能的方法
2018/07/02 HTML / CSS
美国首屈一指的礼品篮供应商:GiftTree
2018/01/06 全球购物
Pottery Barn阿联酋:购买家具、家居装饰及更多
2019/12/08 全球购物
乐观自信演讲稿范文
2014/05/21 职场文书
2015年教师党员公开承诺书
2015/01/22 职场文书
检讨书范文2000字
2015/01/28 职场文书
长城的导游词
2015/01/30 职场文书
外出听课学习心得体会
2016/01/15 职场文书
Python中非常使用的6种基本变量的操作与技巧
2022/03/22 Python