php中使用session_set_save_handler()函数把session保存到MySQL数据库实例


Posted in PHP onNovember 06, 2014

PHP保存session默认的是采用的文件的方式来保存的,这仅仅在文件的空间开销很小的windows上是可以采用的,但是如果我们采用uinx或者是liux上的文件系统的时候,这样的文件系统的文件空间开销是很大的,然而session是要时时刻刻的使用的,大量的用户就要创建很多的session文件,这样对整个的服务器带来性能问题。

另一方面,如果服务器起采用群集的方式的话就不能保持session的一致性,所以我们就绪要采用数据库的方式来保存session,这样,不管有几台服务器同时使用,只要把他们的session保存在一台数据库服务器上就可以保证session的完整了,具体如何来实现请继续看下去。

PHP保存session默认的情况下是采用的文件方式来保存的,我们在PHP的配制文件PHP.ini中可以看到这样的一行:

session.save_handler="files"

这样的意思就是采用文件来保存session 的,要采用数据库来保存的话,我们需要修改成用户模式,改成
session.save_handler="use"

就可以了,但是,这仅仅是说明我门没有采用文件的方式存储session,我们还要选择数据库和建立数据库的表。

建立数据库和数据库的表结构,我们可以采用PHP可以使用的任何的数据库,因为PHP和mysql的结合最好,我就使用mysql来做示例,当然根据你的需要可以改称别的数据库。

创建数据库

create database 'session';

创建表结构
create table 'session'( id char(32) not null , 'user 'char(30), data char(3000) ,primary key ('id') );

PHP保存session编写PHP文件
<?php

$con = mysql_connect("127.0.0.1", "user" , "pass");

mysql_select_db("session");

function open($save_path, $session_name) {

 return(true);

}

function close() {

 return(true);

}

function read($id) {

 if ($result = mysql_query("select * from session where id='$id'")) {

  if ($row = mysql_felth_row($result)) {

   return $row["data"];

  }

 } else {

  return "";

 }

}

function write($id, $sess_data) {

 if ($result = mysql_query("update session set data='$sess_data' where id='$id'")) {

  return true;

 } else {

  return false;

 }

}

function destroy($id) {

 if ($result = mysql_query("delete * from session where id='$id'")) {

  return true;

 } else {

  return false;

 }

}

function gc($maxlifetime) {

 return true;

}

session_set_save_handler("open", "close", "read", "write", "destroy", "gc");

session_start();

// proceed to use sessions normally

保存成为session_user_start.php。

现在我们的PHP保存session的工作就已经完成了,只要你在需要在使用session的时候,把session_user_start.php包含进来.注意,这个文件一定要在文件的第一行包含,然后就像使用文件的session一样的方法使用就可以了。

以上仅仅是个简单教程,在实际的应用中,可以对它封装得更专业些,参考代码如下:

SessionMysql.class.php

<?php

/**

 * SessionMysql 数据库存储类

 */
defined('IN_QIAN') or exit('Access Denied');
class SessionMysql {
 public $lifetime = 1800; // 有效期,单位:秒(s),默认30分钟

 public $db;

 public $table;
 /**

  * 构造函数

  */

 public function __construct() {

  $this->db = Base::loadModel('SessionModel');

  $this->lifetime = Base::loadConfig('system', 'session_lifetime');

  session_set_save_handler(

   array(&$this, 'open'),  // 在运行session_start()时执行

   array(&$this, 'close'),  // 在脚本执行完成 或 调用session_write_close() 或 session_destroy()时被执行,即在所有session操作完后被执行

   array(&$this, 'read'),  // 在运行session_start()时执行,因为在session_start时,会去read当前session数据

   array(&$this, 'write'),  // 此方法在脚本结束和使用session_write_close()强制提交SESSION数据时执行

   array(&$this, 'destroy'), // 在运行session_destroy()时执行

   array(&$this, 'gc')   // 执行概率由session.gc_probability 和 session.gc_divisor的值决定,时机是在open,read之后,session_start会相继执行open,read和gc

  );

  session_start(); // 这也是必须的,打开session,必须在session_set_save_handler后面执行

 }

 /**

  * session_set_save_handler open方法

  *

  * @param $savePath

  * @param $sessionName

  * @return true

  */

 public function open($savePath, $sessionName) {

  return true;

 }

 /**

  * session_set_save_handler close方法

  *

  * @return bool

  */

 public function close() {

  return $this->gc($this->lifetime);

 }

 /**

  * 读取session_id

  *

  * session_set_save_handler read方法

  * @return string 读取session_id

  */

 public function read($sessionId) {

  $condition = array(

   'where' => array(

    'session_id' => $sessionId

   ),

   'fields' => 'data'

  );

  $row = $this->db->fetchFirst($condition);

  return $row ? $row['data'] : '';

 }

 /**

  * 写入session_id 的值

  *

  * @param $sessionId 会话ID

  * @param $data 值

  * @return mixed query 执行结果

  */

 public function write($sessionId, $data) {

  $userId = isset($_SESSION['userId']) ? $_SESSION['userId'] : 0;

  $roleId = isset($_SESSION['roleId']) ? $_SESSION['roleId'] : 0;

  $grouId = isset($_SESSION['grouId']) ? $_SESSION['grouId'] : 0;

  $m = defined('ROUTE_M') ? ROUTE_M : '';

  $c = defined('ROUTE_C') ? ROUTE_C : '';

  $a = defined('ROUTE_A') ? ROUTE_A : '';

  if (strlen($data) > 255) {

   $data = '';

  }

  $ip = get_ip();

  $sessionData = array(

   'session_id' => $sessionId,

   'user_id'  => $userId,

   'ip'   => $ip,

   'last_visit' => SYS_TIME,

   'role_id'  => $roleId,

   'group_id'  => $grouId,

   'm'    => $m,

   'c'    => $c,

   'a'    => $a,

   'data'   => $data,

  );

  return $this->db->insert($sessionData, 1, 1);

 }

 /**

  * 删除指定的session_id

  *

  * @param string $sessionId 会话ID

  * @return bool

  */

 public function destroy($sessionId) {

  return $this->db->delete(array('session_id' => $sessionId));

 }

 /**

  * 删除过期的 session

  *

  * @param $lifetime session有效期(单位:秒)

  * @return bool

 */

 public function gc($lifetime) {

  $expireTime = SYS_TIME - $lifetime;

  return $this->db->delete("`last_visit`<$expireTime");

 }

}

在系统文件的某个地方,实例化这个类即可!

new SessionMysql();
PHP 相关文章推荐
PHP学习散记_编码(json_encode 中文不显示)
Nov 10 PHP
php比较多维数组中值的大小排序实现代码
Sep 08 PHP
ThinkPHP框架任意代码执行漏洞的利用及其修复方法
Jul 04 PHP
ThinkPHP中的三大自动简介
Aug 22 PHP
php实现通用的从数据库表读取数据到数组的函数实例
Mar 21 PHP
4种PHP异步执行的常用方式
Dec 24 PHP
Thinkphp3.2.3分页使用实例解析
Jul 28 PHP
PHP使用PDO调用mssql存储过程的方法示例
Oct 07 PHP
针对thinkPHP5框架存储过程bug重写的存储过程扩展类完整实例
Jun 16 PHP
PHP封装请求类实例分析【基于Yii框架】
Oct 17 PHP
利用PHP内置SERVER开启web服务(本地开发使用)
Jan 22 PHP
PHP设计模式之组合模式定义与应用示例
Feb 01 PHP
php中常见的sql攻击正则表达式汇总
Nov 06 #PHP
php中实现记住密码下次自动登录的例子
Nov 06 #PHP
php网站被挂木马后的修复方法总结
Nov 06 #PHP
调试PHP程序的多种方法介绍
Nov 06 #PHP
php实现singleton()单例模式实例
Nov 06 #PHP
php使用session二维数组实例
Nov 06 #PHP
php函数serialize()与unserialize()用法实例
Nov 06 #PHP
You might like
PHP学习之字符串比较和查找
2011/04/17 PHP
Yii2使用自带的UploadedFile实现的文件上传
2016/06/20 PHP
Phpstorm+Xdebug断点调试PHP的方法
2018/05/14 PHP
docker-compose部署php项目实例详解
2019/07/30 PHP
Aliyun Linux 编译安装 php7.3 tengine2.3.2 mysql8.0 redis5的过程详解
2020/10/20 PHP
JS网络游戏-(模拟城市webgame)提供的一些例子下载
2007/10/14 Javascript
比较全的JS checkbox全选、取消全选、删除功能代码
2008/12/19 Javascript
JavaScript.The.Good.Parts阅读笔记(一)假值与===运算符
2010/11/16 Javascript
js的写法基础分析
2011/01/17 Javascript
基于jquery的图片轮播 tab切换组件
2012/07/19 Javascript
jQuery提交表单ajax查询实例代码
2012/10/07 Javascript
根据选择不同的下拉值出现相对应的文本输入框
2013/08/01 Javascript
动态改变div的z-index属性的简单实例
2013/08/08 Javascript
js网页实时倒计时精确到秒级
2014/02/10 Javascript
小结Node.js中非阻塞IO和事件循环
2014/09/18 Javascript
Javascript中封装window.open解决不兼容问题
2014/09/28 Javascript
Javascript中获取对象的原型对象的方法小结
2015/02/25 Javascript
基于javascript实现样式清新图片轮播特效
2016/03/30 Javascript
老生常谈的跨域处理
2017/01/11 Javascript
利用JQuery操作iframe父页面、子页面的元素和方法汇总
2017/09/10 jQuery
AngularJS实现的简单拖拽功能示例
2018/01/02 Javascript
关于vue状态过渡transition不起作用的原因解决
2019/04/09 Javascript
JavaScript遍历查找数组中最大值与最小值的方法示例
2019/05/24 Javascript
python和C语言混合编程实例
2014/06/04 Python
Python高级应用实例对比:高效计算大文件中的最长行的长度
2014/06/08 Python
深入理解Python中各种方法的运作原理
2015/06/15 Python
Python使用回溯法子集树模板获取最长公共子序列(LCS)的方法
2017/09/08 Python
python2.7+selenium2实现淘宝滑块自动认证功能
2018/02/24 Python
完美解决安装完tensorflow后pip无法使用的问题
2018/06/11 Python
Keras load_model 导入错误的解决方式
2020/06/09 Python
如何用PHP实现邮件发送
2012/12/26 面试题
我的画教学反思
2014/04/28 职场文书
优秀实习生主要事迹
2014/05/29 职场文书
导游词之山西-五老峰
2019/10/07 职场文书
在Java中Collection的一些常用方法总结
2021/06/13 Java/Android
mysql 8.0.27 绿色解压版安装教程及配置方法
2022/04/20 MySQL