将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的配置文件php.ini
Oct 09 PHP
利用static实现表格的颜色隔行显示
Oct 09 PHP
php简单封装了一些常用JS操作
Feb 25 PHP
使用Xdebug调试和优化PHP程序之[1]
Apr 17 PHP
php IP转换整形(ip2long)的详解
Jun 06 PHP
PHP实现生成唯一编号(36进制的不重复编号)
Jul 01 PHP
twig模板常用语句实例小结
Feb 04 PHP
ECshop 迁移到 PHP7版本时遇到的兼容性问题
Feb 15 PHP
PHP 闭包详解及实例代码
Sep 28 PHP
老生常谈php 正则中的i,m,s,x,e分别表示什么
Mar 02 PHP
PHP实现的最大正向匹配算法示例
Dec 19 PHP
在Laravel中使用GuzzleHttp调用第三方服务的API接口代码
Oct 15 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中strtr字符串替换用法详解
2014/11/26 PHP
php实现的数字验证码及数字运算验证码
2015/07/30 PHP
PHP实现网站应用微信登录功能详解
2019/04/11 PHP
JavaScript面象对象设计
2008/04/28 Javascript
document.write()及其输出内容的样式、位置控制
2013/08/12 Javascript
jquery实现侧边弹出的垂直导航
2014/12/09 Javascript
javascript操作表格排序实例分析
2015/05/06 Javascript
跟我学习javascript的this关键字
2020/05/28 Javascript
浅析JavaScript中命名空间namespace模式
2016/06/22 Javascript
AngularJS 视图详解及示例代码
2016/08/17 Javascript
js倒计时小实例(多次定时)
2016/12/08 Javascript
angularjs路由传值$routeParams详解
2020/09/05 Javascript
浅谈 vue 中的 watcher
2017/12/04 Javascript
Vue EventBus自定义组件事件传递
2018/06/25 Javascript
微信小程序模板template简单用法示例
2018/12/04 Javascript
在antd4.0中Form使用initialValue操作
2020/11/02 Javascript
[03:08]迎霜节狂欢!2018年迎霜节珍藏Ⅰ一览
2018/12/25 DOTA
[01:04:29]DOTA2-DPC中国联赛 正赛 Phoenix vs XG BO3 第二场 1月31日
2021/03/11 DOTA
Python迭代用法实例教程
2014/09/08 Python
Python脚本实现下载合并SAE日志
2015/02/10 Python
Python 爬取携程所有机票的实例代码
2018/06/11 Python
基于pycharm实现批量修改变量名
2020/06/02 Python
Django如何使用asyncio协程和ThreadPoolExecutor多线程
2020/10/12 Python
弄清Pytorch显存的分配机制
2020/12/10 Python
你正在寻找的CSS3 动画技术
2011/07/27 HTML / CSS
css3实现背景模糊的三种方式(小结)
2020/05/15 HTML / CSS
送给他或她的礼物:FUN.com
2018/08/17 全球购物
晚归检讨书
2014/02/19 职场文书
班子成员四风问题自我剖析材料
2014/09/29 职场文书
国际贸易实务实训报告
2014/11/05 职场文书
财务工作失职检讨书
2014/11/21 职场文书
三八红旗手事迹材料
2014/12/26 职场文书
医院见习总结
2015/06/24 职场文书
教师远程培训心得体会
2016/01/09 职场文书
golang gopm get -g -v 无法获取第三方库的解决方案
2021/05/05 Golang
解决Mysql的left join无效及使用的注意事项说明
2021/07/01 MySQL