将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 相关文章推荐
PHP3 safe_mode 失效漏洞
Oct 09 PHP
php多文件上传功能实现原理及代码
Apr 18 PHP
使用php 获取时间今天明天昨天时间戳的详解
Jun 20 PHP
PHP使用json_encode函数时不转义中文的解决方法
Nov 12 PHP
php与Mysql的一些简单的操作
Feb 26 PHP
php验证码实现代码(3种)
Sep 07 PHP
浅谈PHP的排列组合(如输入a,b,c 输出他们的全部组合)
Mar 14 PHP
PHP操作MySQL中BLOB字段的方法示例【存储文本与图片】
Sep 15 PHP
自写的利用PDO对mysql数据库增删改查操作类
Feb 19 PHP
laravel框架路由分组,中间件,命名空间,子域名,路由前缀实例分析
Feb 18 PHP
php设计模式之职责链模式实例分析【星际争霸游戏案例】
Mar 27 PHP
Yii 框架使用数据库(databases)的方法示例
May 19 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
杏林同学录(四)
2006/10/09 PHP
PHP与服务器文件系统的简单交互
2016/10/21 PHP
PHP中OpenSSL加密问题整理
2017/12/14 PHP
php微信公众号开发之欢迎老朋友
2018/10/20 PHP
js 实现无缝滚动 兼容IE和FF
2009/07/15 Javascript
javascript 面向对象编程 万物皆对象
2009/09/17 Javascript
jquery 模拟类搜索框自动完成搜索提示功能(改进)
2010/05/24 Javascript
javascript客户端解决方案 缓存提供程序
2010/07/14 Javascript
Js,alert出现乱码问题的解决方法
2013/06/19 Javascript
jquery如何扑捉回车键触发的事件
2014/04/24 Javascript
Visual Studio中js调试的方法图解
2014/06/30 Javascript
JavaScript实现按Ctrl键打开新页面
2014/09/04 Javascript
Angular下H5上传图片的方法(可多张上传)
2017/01/09 Javascript
javascript实现延时显示提示框效果
2017/06/01 Javascript
js制作简单的音乐播放器的示例代码
2017/08/28 Javascript
webpack打包并将文件加载到指定的位置方法
2018/02/22 Javascript
Node.js动手撸一个静态资源服务器的方法
2019/03/09 Javascript
详解bootstrap-fileinput文件上传控件的亲身实践
2019/03/21 Javascript
简单了解Ajax表单序列化的实现方法
2019/06/14 Javascript
微信小程序实现手势滑动效果
2019/08/26 Javascript
vue滚动插件better-scroll使用详解
2019/10/18 Javascript
[38:21]2018DOTA2亚洲邀请赛3月30日 小组赛A组 LGD VS Newbee
2018/03/31 DOTA
python实现任意位置文件分割的实例
2018/12/14 Python
CentOS7下安装python3.6.8的教程详解
2020/01/03 Python
python 读取、写入txt文件的示例
2020/09/27 Python
Python3 用matplotlib绘制sigmoid函数的案例
2020/12/11 Python
一款纯css3实现的圆形旋转分享按钮旋转角度可自己调整
2014/09/02 HTML / CSS
香蕉共和国加拿大官网:Banana Republic加拿大
2018/08/06 全球购物
消防安全管理制度
2014/02/01 职场文书
委托公证书
2014/04/08 职场文书
党的群众路线教育学习材料
2014/05/12 职场文书
2014年医德医风工作总结
2014/11/13 职场文书
2014年乡镇纪委工作总结
2014/12/19 职场文书
2015年小学开学寄语
2015/02/27 职场文书
简述python四种分词工具,盘点哪个更好用?
2021/04/13 Python
Python获取江苏疫情实时数据及爬虫分析
2021/08/02 Python