将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+DBM的同学录程序(3)
Oct 09 PHP
mysql4.1以上版本连接时出现Client does not support authentication protocol问题解决办法
Mar 15 PHP
PHP添加MySQL数据记录代码
Jun 07 PHP
php使用strtotime和date函数判断日期是否有效代码分享
Dec 25 PHP
Drupal简体中文语言包安装教程
Sep 27 PHP
PHP实现指定字段的多维数组排序函数分享
Mar 09 PHP
php实现将数组转换为XML的方法
Mar 09 PHP
PHP的Yii框架使用中的一些错误解决方法与建议
Aug 21 PHP
分享ThinkPHP3.2中关联查询解决思路
Sep 20 PHP
100行PHP代码实现socks5代理服务器
Apr 28 PHP
PHP中$GLOBALS与global的区别详解
Mar 21 PHP
PHP isset()及empty()用法区别详解
Aug 29 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中的CMS的涵义
2007/03/11 PHP
PHP字符串的编码问题的详细介绍
2013/04/27 PHP
PHP延迟静态绑定示例分享
2014/06/22 PHP
Ubuntu上安装yaf扩展的方法
2018/01/29 PHP
对 lightbox JS 图片控件进行了一下改造, 使其他支持复杂的图片说明
2010/03/20 Javascript
修改file按钮的默认样式实现代码
2013/04/23 Javascript
DOM基础教程之模型中的模型节点
2015/01/19 Javascript
详解在WebStorm中添加Vue.js单文件组件的高亮及语法支持
2017/10/21 Javascript
vue环境搭建简单教程
2017/11/07 Javascript
layui table复选框禁止某几条勾选的实例
2019/09/20 Javascript
js代码实现轮播图
2020/05/04 Javascript
[01:22:19]EG vs TNC Supermajor小组赛B组败者组第一轮 BO3 第二场 6.2
2018/06/03 DOTA
用Python进行行为驱动开发的入门教程
2015/04/23 Python
python批量添加zabbix Screens的两个脚本分享
2017/01/16 Python
Python爬取qq music中的音乐url及批量下载
2017/03/23 Python
python读取中文txt文本的方法
2018/04/12 Python
python+POP3实现批量下载邮件附件
2018/06/19 Python
pygame游戏之旅 添加碰撞效果的方法
2018/11/20 Python
对python pandas读取剪贴板内容的方法详解
2019/01/24 Python
Python使用os.listdir()和os.walk()获取文件路径与文件下所有目录的方法
2019/04/01 Python
Python中print函数简单使用总结
2019/08/05 Python
Django实现分页显示效果
2019/10/31 Python
Python如何使用argparse模块处理命令行参数
2019/12/11 Python
Python拼接字符串的7种方式详解
2020/03/19 Python
python批量替换文件名中的共同字符实例
2020/03/05 Python
BrandAlley英国:法国折扣奢侈品网上零售商
2017/07/03 全球购物
旅游管理专业个人求职信范文
2013/12/24 职场文书
农村婚礼证婚词
2014/01/08 职场文书
经贸韩语专业大学生职业规划
2014/02/14 职场文书
团日活动总结范文
2014/04/25 职场文书
汉语言文学专业求职信
2014/06/19 职场文书
关于读书的演讲稿400字
2014/08/27 职场文书
2015年社区关工委工作总结
2015/04/03 职场文书
防震减灾主题班会
2015/08/14 职场文书
读《解忧杂货店》有感:请相信一切都是最好的安排
2019/11/07 职场文书