将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使之能同时支持GIF和JPEG
Oct 09 PHP
PHP实现分页的一个示例
Oct 09 PHP
php5 and xml示例
Nov 22 PHP
PHP面向对象的使用教程 简单数据库连接
Nov 25 PHP
谨慎使用PHP的引用原因分析
Sep 06 PHP
PHP中array_merge和array相加的区别分析
Jun 17 PHP
Linux下创建nginx脚本-start、stop、reload…
Aug 03 PHP
PHP Reflection API详解
May 12 PHP
Smarty foreach控制循环次数的一些方法
Jul 01 PHP
php进行ip地址掩码运算处理的方法
Jul 11 PHP
tp5框架基于Ajax实现列表无刷新排序功能示例
Feb 10 PHP
JS中彻底删除JSON对象组成的数组中的元素
Sep 22 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
当海贼王变成JOJO风
2020/03/02 日漫
PHP模拟SQL Server的两个日期处理函数
2006/10/09 PHP
聊天室php&amp;mysql(一)
2006/10/09 PHP
PHP中file_exists函数不支持中文名的解决方法
2014/07/26 PHP
thinkphp框架使用JWTtoken的方法详解
2019/10/10 PHP
jquery 插件学习(三)
2012/08/06 Javascript
JS分页控件 可用于无刷新分页
2013/07/23 Javascript
js取float型小数点后两位数的方法
2014/01/18 Javascript
bootstrap改变按钮加载状态
2014/12/01 Javascript
JavaScript测试工具之Karma-Jasmine的安装和使用详解
2015/12/03 Javascript
Node.js编写组件的三种实现方式
2016/02/25 Javascript
轻松掌握JavaScript单例模式
2016/08/25 Javascript
Javascript基于jQuery UI实现选中区域拖拽效果
2016/11/25 Javascript
JavaScript数组复制详解
2017/02/02 Javascript
elementui的默认样式修改方法
2018/02/23 Javascript
JavaScript中AOP的实现与应用
2019/05/06 Javascript
使用preload预加载页面资源时注意事项
2020/02/03 Javascript
微信小程序实现下拉加载更多商品
2020/12/29 Javascript
python函数参数*args**kwargs用法实例
2013/12/04 Python
记录Django开发心得
2014/07/16 Python
python实现AES和RSA加解密的方法
2019/03/28 Python
django 使用 PIL 压缩图片的例子
2019/08/16 Python
pytorch 改变tensor尺寸的实现
2020/01/03 Python
python简单实现最大似然估计&amp;scipy库的使用详解
2020/04/15 Python
matplotlib交互式数据光标mpldatacursor的实现
2021/02/03 Python
CSS3 flex布局之快速实现BorderLayout布局
2015/12/03 HTML / CSS
关于解决iframe标签嵌套问题的解决方法
2020/03/04 HTML / CSS
俄罗斯卫浴采暖及维修用品超级市场:Dkrussia
2020/05/12 全球购物
如何清空Session
2015/02/23 面试题
理工类毕业自我鉴定
2014/02/20 职场文书
关于读书的演讲稿600字
2014/08/27 职场文书
再婚婚前财产协议书范本
2014/10/19 职场文书
2016预备党员培训心得体会
2016/01/08 职场文书
python之np.argmax()及对axis=0或者1的理解
2021/06/02 Python
Mybatis-plus在项目中的简单应用
2021/07/01 Java/Android
InterProcessMutex实现zookeeper分布式锁原理
2022/03/21 Java/Android