PHP session 写入数据库中的方法
首先解释下为什么要把session 写到数据库中呢,session 一般默认是以文件的形式放在php.ini 配置的目录中的, 如果你的网站实现了多台服务器负载均衡,这样用户访问你的网站,可能进入的服务器就不同,如果没有实现吧session 文件在服务器上实现同步,那么就可能会出现session 丢失问题,最常见的例子就是,我登陆了后台,点着点着 就又让重新登录了,这是个典型的session 没有同步而引起的session 丢失的问题。
解决方案当然有很多,现在介绍一个就是把用户的session 写入到数据库中去,这样session 都从数据库中读取,就不会有丢失的情况发生。
首先要更改php.ini 里面
session.save_handler = files
为:
session.save_handler = user
PHP 有个session_set_save_handler() 函数 ,这个函数就是自定义处理session 的机制,一般 要定义
'open', 'close', 'read', 'write','destroy', 'gc'
这几个函数
下面是个session 写入数据库的一个类
<?php
class SessionToDB
{
private $_path = null;
private $_name = null;
private $_pdo = null;
private $_ip = null;
private $_maxLifeTime = 0; public function __construct(PDO $pdo)
{
//注册处理session 的函数
session_set_save_handler(
array(&$this, 'open'),
array(&$this, 'close'),
array(&$this, 'read'),
array(&$this, 'write'),
array(&$this, 'destroy'),
array(&$this, 'gc')
); $this->_pdo = $pdo;
$this->_ip = !empty($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null;
$this->_maxLifeTime = ini_get('session.gc_maxlifetime');
} public function open($path,$name)
{
return true;
} public function close()
{
return true;
}
//读取函数
public function read($id)
{
$sql = 'SELECT * FROM session where PHPSESSID = ?';
$stmt = $this->_pdo->prepare($sql);
$stmt->execute(array($id)); if (!$result = $stmt->fetch(PDO::FETCH_ASSOC)) {
return null;
} elseif ($this->_ip != $result['client_ip']) {
return null;
} elseif ($result['update_time']+$this->_maxLifeTime < time()){
$this->destroy($id);
return null;
} else {
return $result['data'];
}
}
//写入函数
public function write($id,$data)
{
$sql = 'SELECT * FROM session where PHPSESSID = ?';
$stmt = $this->_pdo->prepare($sql);
$stmt->execute(array($id)); if ($result = $stmt->fetch(PDO::FETCH_ASSOC)) {
if ($result['data'] != $data) {
$sql = 'UPDATE session SET update_time =? , data = ? WHERE PHPSESSID = ?'; $stmt = $this->_pdo->prepare($sql);
$stmt->execute(array(time(), $data, $id));
}
} else {
if (!empty($data)) {
$sql = 'INSERT INTO session (PHPSESSID, update_time, client_ip, data) VALUES (?,?,?,?)';
$stmt = $this->_pdo->prepare($sql);
$stmt->execute(array($id, time(), $this->_ip, $data));
}
}
return true;
}
//销毁函数
public function destroy($id)
{
$sql = 'DELETE FROM session WHERE PHPSESSID = ?';
$stmt = $this->_pdo->prepare($sql);
$stmt->execute(array($id));
return true;
}
//这个函数执行的几率有php.ini 控制
public function gc($maxLifeTime)
{
$sql = 'DELETE FROM session WHERE update_time < ?';
$stmt = $this->_pdo->prepare($sql);
$stmt->execute(array(time() - $maxLifeTime));
return true;
}
}
//调用方式
ini_set('session.save_handler','user');//更改为user 方式
ini_set('session.gc_maxlifetime', '86400');//session 最大有效期可以不设
$dbname='数据库名称';
$dbuser='用户名';
$dbpwd=密码'';
$dbhost='主机地址';
try{
$pdo = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser,$dbpwd);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); new SessionToDB($pdo);
session_start();
} catch(PDOException $e) {
echo 'Error: '.$e->getMessage();
}
?>
数据库结构:
CREATE TABLE `session` (
`PHPSESSID` varchar(50) NOT NULL,
`update_time` int(10) NOT NULL,
`client_ip` varchar(25) NOT NULL,
`data` text NOT NULL,
PRIMARY KEY (`PHPSESSID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
当然解决这个问题的方法很多,思路就是把session 放到服务器 共用的地方.
PHP session 写入数据库中的方法的更多相关文章
- 将Session写入数据库
使用session_set_save_handler()函数,将Session的内容写入数据库 <?php /* *@author Fahy *@link http://home.cnblogs ...
- DataTable数据批量写入数据库三种方法比较
DataTable数据批量写入数据库三种方法比较 标签: it 分类: C#1) insert循环插入:2) sqldataadapter.update(dataset,tablename); ...
- DataTable 数据批量写入数据库三种方法比较
DataTable数据批量写入数据库三种方法比较 1) insert循环插入: 2) sqldataadapter.update(dataset,tablename); 3) sqlbul ...
- C#将图片存放到SQL SERVER数据库中的方法
本文实例讲述了C#将图片存放到SQL SERVER数据库中的方法.分享给大家供大家参考.具体如下: 第一步: ? 1 2 3 4 5 6 7 8 9 10 //获取当前选择的图片 this.pictu ...
- 已知数据库中存在表tb_book2,通过在图书信息界面填写书本的基本信息,然后提交后写入数据库中的表格中。需要对提交的信息进行修改,信息填入不能为空,为空则则有提示。
jsp结合SQLSERVER向数据库中的表添加图书信息. 已知数据库中存在表tb_book2,通过在图书信息界面填写书本的基本信息,然后提交后写入数据库中的表格中.需要对提交的信息进行修改,信息填入不 ...
- 怎样借助log4j把日志写入数据库中
log4j是一个优秀的开源日志记录项目.我们不仅能够对输出的日志的格式自定义,还能够自定义日志输出的目的地,比方:屏幕.文本文件,数据 库,甚至能通过socket输出.本节使用MySQ ...
- 【繁星Code】如何在EF将实体注释写入数据库中
最近在项目中需要把各个字段的释义写到数据库中,该项目已经上线很长时间了,数据库中的字段没有上千也有上百个,要是一个项目一个项目打开然后再去找对应字段查看什么意思,估计要到明年过年了.由于项目中使用En ...
- SQL语句:把Excel文件中数据导入SQL数据库中的方法
1.从Excel文件中,导入数据到SQL数据库情况一.如果接受数据导入的表不存在 select * into jd$ from OPENROWSET('MICROSOFT.JET.OLEDB.4.0' ...
- dede 忘记密码在数据库中修改方法
如何找回或修改dedecms后台管理员登录密码呢? 一个客户把密码忘了,找了很长一会没几个靠谱的回答,dede是使用md5加密,但是,它是显示32位md5加密码从第6位开始的20位 方法是直接修改其m ...
随机推荐
- 「Vue」过滤器
#全局过滤器要写在var vue之前<td>{{item.time | ctime }}</td>Vue.filter('ctime'(过滤器名),function(data( ...
- windows下静态编译pthread
1. Building the library as a statically linkable library-------------------------------------------- ...
- Mac下配置环境变量(转)
说明:Mac下一般使用bash作为默认shell 一.Mac系统的环境变量,加载顺序为: /etc/profile /etc/paths ~/.bash_profile ~/.bash_login ~ ...
- shell操作典型案例--FTP操作
从FTP服务器上下载文件或上传文件到FTP服务器是生产环境中比较常见的场景之一. shell操作FTP的方式整理如下: 思路一:使用shell调用ftp等客户端 使用FTP方式,通过shell调用ft ...
- 25、LinkedList特有方法
LinkedList特有方法 public void addFirst(E e)及addLast(E e) public E getFirst()及getLast() public E removeF ...
- Win7下VS2010不能链接问题
装了2012准备学VC++窗体开发,然后发现手边只有VS2010的教程,于是卸掉VS2012改装VS2010,结果发现不管写啥,链接时都报错“error Link1123 转到coff期间失败”. 于 ...
- 关于项目中根据当前数据库中最大ID生成下一个ID问题——(五)
1.关于部门管理时候根据上级产生下级部门ID的问题(传入一个参数是上级部门id)
- oracle数据类型表
set SERVEROUTPUT ON declare v_char ); v_varchar2 ); begin v_char:='java'; v_varchar2:='java'; DBMS_O ...
- 数论-求n以内的质数
一.埃拉托斯特尼筛法 名字很高大上,然而并没有什么卵用…… 思路: 在把<=√n的质数所有的<=n的倍数剔除,剩下的就都是质数了,很容易理解…… 复杂度O(nloglogn) #inclu ...
- linux用户权限 -> 系统用户管理
用户基本概述: Linux用户属于多用户操作系统,在windows中,可以创建多个用户,但不允许同一时间多个用户进行系统登陆,但是Linux可以同时支持多个用户同时登陆操作系统,登陆后互相之间并不影响 ...