将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中文件下载功能实现超详细流程分析
Jun 13 PHP
php中explode与split的区别介绍
Oct 03 PHP
php解析xml提示Invalid byte 1 of 1-byte UTF-8 sequence错误的处理方法
Nov 14 PHP
ThinkPHP跳转页success及error模板实例教程
Jul 17 PHP
php随机生成数字字母组合的方法
Mar 18 PHP
PHP实现CSV文件的导入和导出类
Mar 24 PHP
Zend Framework动作助手FlashMessenger用法详解
Mar 05 PHP
thinkPHP中_initialize方法实例分析
Dec 05 PHP
关于ThinkPhp 框架表单验证及ajax验证问题
Jul 19 PHP
总结PHP代码规范、流程规范、git规范
Jun 18 PHP
laravel框架模板之公共模板、继承、包含实现方法分析
Aug 30 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静态变量当缓存的方法
2013/11/13 PHP
ThinkPHP文件缓存类代码分享
2015/04/22 PHP
yii2.0数据库迁移教程【多个数据库同时同步数据】
2016/10/08 PHP
PHP验证终端类型是否为手机的简单实例
2017/02/07 PHP
CodeIgniter整合Smarty的方法详解
2017/08/25 PHP
PHP删除数组中特定元素的两种方法
2019/02/28 PHP
使用Javascript和DOM Interfaces来处理HTML
2006/10/09 Javascript
jquery常用技巧及常用方法列表集合
2011/04/06 Javascript
javascript淡入淡出效果的实现思路
2012/03/31 Javascript
javascript计算星座属相(十二生肖属相)示例代码
2014/01/09 Javascript
JavaScript和CSS交互的方法汇总
2014/12/02 Javascript
JS动态创建元素的两种方法
2016/04/20 Javascript
详解JavaScript设计模式开发中的桥接模式使用
2016/05/18 Javascript
js实现文件上传功能 后台使用MultipartFile
2018/09/08 Javascript
详解JavaScript的变量
2019/04/04 Javascript
Node.js事件的正确使用方法
2019/04/05 Javascript
小程序云开发获取不到数据库记录的解决方法
2019/05/18 Javascript
详解基于Vue的支持数据双向绑定的select组件
2019/09/02 Javascript
[48:02]Ti4循环赛第三日 VG vs Liquid和NEWBEE vs DK
2014/07/12 DOTA
[01:12:40]DOTA2-DPC中国联赛 正赛 DLG vs XG BO3 第三场 1月25日
2021/03/11 DOTA
python实现支持目录FTP上传下载文件的方法
2015/06/03 Python
Python os.rename() 重命名目录和文件的示例
2018/10/25 Python
Python Numpy 实现交换两行和两列的方法
2019/06/26 Python
Python列表(list)所有元素的同一操作解析
2019/08/01 Python
浅谈keras中Dropout在预测过程中是否仍要起作用
2020/07/09 Python
python如何遍历指定路径下所有文件(按按照时间区间检索)
2020/09/14 Python
Python lxml库的简单介绍及基本使用讲解
2020/12/22 Python
美国在线旅行社:Crystal Travel
2018/09/11 全球购物
Topshop美国官网:英国快速时尚品牌
2019/05/16 全球购物
HomeAway英国:全球领先的度假租赁在线市场
2020/02/03 全球购物
.net软件工程师面试题
2015/03/31 面试题
会计系中文个人求职信
2013/12/24 职场文书
教师简历自我评价
2014/02/03 职场文书
《圆明园的毁灭》教学反思
2014/02/28 职场文书
党的群众路线教育实践活动学习心得体会
2014/03/03 职场文书
联谊会主持词
2014/03/26 职场文书