阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

PHP数据库保存session会话

414次阅读
没有评论

共计 4179 个字符,预计需要花费 11 分钟才能阅读完成。

前言:

在默认的情况下,PHP 会把全部的会话数据保存在服务器上的文本文件里面,这些文件通常都是保存在服务器上的临时目录里边。

那为什么我们要把 session 会话保存在数据库中呢?

  1. 主要原因: 提高系统的安全性。在共享服务器上,在没有进行特别的设置,所有的网站站点都会使用同一个临时目录,这意味着数十个程序都在同一个位置对文件进行读写操作。不仅速度下降了,而且别人也有可能窃取到我的站点的用户数据。
  2. 把会话数据保存到数据库还可以更方便的搜索 web 站点会话的更多信息,我们可以查询活动会话的数量(同时在线的用户量),还可以对会话数据进行备份。
  3. 假如我的站点同时运行于多个服务器,那么某个用户在一个会话过程中,可能会对不同的服务器发送多个请求,但是会话数据如果保存在某一个服务器上,那么其他服务器就不能使用到这些会话数据。假如我的某一台服务器仅仅是数据库的角色,那你把会话数据全保存在数据库中,不是很方便么?

1、创建会话表

由于 session 数据是保存在服务器上面的,而在客户端中保存的是一个索引(sessionID), 这个索引对应于服务器上的某一条 session 数据。因此该表必须包含的两个字段是 id、data,还有就是会话会有过期时间,所以在这里还有个字段就是 last_accessed,这里我把该表建在 test 数据库下:

CREATE TABLE sessions(id CHAR(32) NOT NULL,
    data TEXT,
    last_accessed TIMESTAMP NOT NULL,
    PRIMARY KEY(id)
);

PHP 数据库保存 session 会话

PS:如果程序需要在会话保存大量的数据,则 data 字段可能就需要定义为 MEDIUMTEXT 或 LONGTEXT 类型了。

2、定义会话函数:

这里我们主要有两个步骤:

  1. 定义与数据库交互的函数
  2. 使 PHP 能使用这些自定义函数

在第二步中,是通过调用函数 session_set_save_handler() 来完成的,调用它需要 6 个参数,分别是 open( 启动会话)、close(关闭会话)、read(读取会话)、write(写入会话)、destroy(销毁会话)、clean(垃圾回收)。

我们新建 php 文件 sessions.inc.php,代码如下:

<?php

$sdbc = null;  // 数据库连接句柄,在后面的函数里面让它成为全局变量 

// 启动会话 
function open_session()
{
    global $sdbc;      // 使用全局的 $sdbc
    $sdbc = mysqli_connect('localhost', 'root', 'lsgogroup', 'test');     // 数据库 test
    if (!$sdbc) {return false;
    }
    return true;
}

// 关闭会话 
function close_session()
{
    global $sdbc;
    return mysqli_close($sdbc);
}

// 读取会话数据 
function read_session($sid)
{
    global $sdbc;
    $sql = sprintf("SELECT data FROM sessions WHERE id='%s'", mysqli_real_escape_string($sdbc, $sid));
    $res = mysqli_query($sdbc, $sql);
    if (mysqli_num_rows($res) == 1) {list($data) = mysqli_fetch_array($res, MYSQLI_NUM);
        return $data;
    } else {return '';
    }
}

// 写入会话数据 
function write_session($sid, $data)
{
    global $sdbc;
    $sql = sprintf("INSERT INTO sessions(id,data,last_accessed) VALUES('%s','%s','%s')", mysqli_real_escape_string($sdbc, $sid), mysqli_real_escape_string($sdbc, $data), date("Y-m-d H:i:s", time()));
    $res = mysqli_query($sdbc, $sql);
    if (!$res) {return false;
    }
    return true;
}

// 销毁会话数据 
function destroy_session($sid)
{
    global $sdbc;
    $sql = sprintf("DELETE FROM sessions WHERE id='%s'", mysqli_real_escape_string($sdbc, $sid));
    $res = mysqli_query($sdbc, $sql);
    $_SESSION = array();
    if (!mysqli_affected_rows($sdbc) == 0) {return false;
    }
    return true;
}

// 执行垃圾回收(删除旧的会话数据)
function clean_session($expire)
{
    global $sdbc;
    $sql = sprintf("DELETE FROM sessions WHERE DATE_ADD(last_accessed,INTERVAL %d SECOND)<NOW()", (int)$expire);
    $res = mysqli_query($sdbc, $sql);
    if (!$res) {return false;
    }
    return true;
}

// 告诉 PHP 使用会话处理函数 
session_set_save_handler('open_session', 'close_session', 'read_session', 'write_session', 'destroy_session', 'clean_session');

// 启动会话,该函数必须在 session_set_save_handler() 函数后调用,不然我们所定义的函数就没法起作用了。
session_start();

// 由于该文件被包含在需要使用会话的 php 文件里面,因此不会为其添加 PHP 结束标签 

PS:

  1. 处理“读取”函数外,其他函数必须返回一个布尔值,“读取”函数必须返回一个字符串。

  2. . 每次会话启动时,“打开”和“读取”函数将会立即被调用。当“读取”函数被调用的时候,可能会发生垃圾回收过程。

  3. 当脚本结束时,“写入”函数就会被调用,然后就是“关闭”函数,除非会话被销毁了,而这种情况下,“写入”函数不会被调用。但是,在“关闭”函数之后,“销毁”函数将会被调用。

  4. .session_set_save_handler() 函数参数顺序不能更改,因为它们一一对应 open、close、read、、、、

  5. 会话数据最后将会以数据序列化的方式保存在数据库中。

3、使用新会话处理程序

使用新会话处理程序只是调用 session_set_save_handler() 函数,使我们的自定义函数能够被自动调用而已。其他关于会话的操作都没有发生变化(以前怎么用现在怎么用,我们的函数会在后台自动被调用),包括在会话中存储数据,访问保存的会话数据以及销毁数据。

在这里,我们新建 sessions.php 文件,该脚本将在没有会话信息时���建一些会话数据,并显示所有的会话数据,在用户点击‘log out’(注销)时销毁会话数据。

代码:

<?php

// 引入 sessions.inc.php 文件,即上面的代码 
require('sessions.inc.php');

?>
<!doctype html>
<html lang='en'>
<head>
    <meta charset="utf-8">
    <title>DB session test</title>
</head>
<body>
<?php

// 创建会话数据 
if(empty($_SESSION)){$_SESSION['blah'] = "umlaut";
    $_SESSION['this'] = 12345;
    $_SESSION['that'] = 'blue';
    echo "<p>Session data stored</p>";
}else{echo "<p>Session data exists:<pre>".print_r($_SESSION,1)."</pre></p>";
}

if(isset($_GET['logout'])){// 销毁会话数据 
    session_destroy();
    echo "<p>session destroyed</p>";
}else{echo "<a href='https://www.linuxidc.com/Linux/2017-05/sessions.php?logout=true'>log out</a>";
}


echo "<p>session data :<pre>".print_r($_SESSION,1)."</pre></p>";

echo '</body></html>';

session_write_close();  // 下面重点解析 
?>

</body>

解析 session_write_close():

顾名思义,该函数就是先写入会话数据,然后关闭 session 会话,按道理这两步在脚本执行完后会自动执行,为什么我们还要显式调用它呢?因为这里涉及到了数据库的连接!

由于我们知道,PHP 会在脚本执行完后自动关闭数据库的所有连接,而同时会话函数会尝试向数据库写入数据并关闭连接。这样一来就会导致会话数据没法写入数据库,并且出现一大堆错误,例如 write_session()、close_session() 函数中都有用到数据库的连接。

为了避免以上说的问题,我们在脚本执行完之前调用 session_write_close() 函数,他就会调用“写入”函数和“关闭”函数,而此时数据库连接还是存在的!

PS:在使用 header() 函数重定向浏览器之前也应该调用 session_write_close() 函数,假如有数据库的操作时!

4、测试使用

在浏览器中打开 sessions.php,刷新页面,然后再看看数据库有没有添加数据。在另一个浏览器打开 sessions.php,看看数据库中有没有添加另一条数据。

本文永久更新链接地址 :http://www.linuxidc.com/Linux/2017-05/143595.htm

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-21发表,共计4179字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中

星哥玩云

星哥玩云
星哥玩云
分享互联网知识
用户数
4
文章数
19351
评论数
4
阅读量
7978932
文章搜索
热门文章
星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛 NAS-6:抖音视频同步工具,视频下载自动下载保存 前言 各位玩 NAS 的朋友好,我是星哥!...
星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛 NAS-3:安装飞牛 NAS 后的很有必要的操作 前言 如果你已经有了飞牛 NAS 系统,之前...
我把用了20年的360安全卫士卸载了

我把用了20年的360安全卫士卸载了

我把用了 20 年的 360 安全卫士卸载了 是的,正如标题你看到的。 原因 偷摸安装自家的软件 莫名其妙安装...
再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见 zabbix!轻量级自建服务器监控神器在 Linux 的完整部署指南 在日常运维中,服务器监控是绕不开的...
飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

飞牛 NAS 中安装 Navidrome 音乐文件中文标签乱码问题解决、安装 FntermX 终端 问题背景 ...
阿里云CDN
阿里云CDN-提高用户访问的响应速度和成功率
随机文章
150元打造低成本NAS小钢炮,捡一块3865U工控板

150元打造低成本NAS小钢炮,捡一块3865U工控板

150 元打造低成本 NAS 小钢炮,捡一块 3865U 工控板 一块二手的熊猫 B3 工控板 3865U,搭...
颠覆 AI 开发效率!开源工具一站式管控 30+大模型ApiKey,秘钥付费+负载均衡全搞定

颠覆 AI 开发效率!开源工具一站式管控 30+大模型ApiKey,秘钥付费+负载均衡全搞定

  颠覆 AI 开发效率!开源工具一站式管控 30+ 大模型 ApiKey,秘钥付费 + 负载均衡全...
安装Black群晖DSM7.2系统安装教程(在Vmware虚拟机中、实体机均可)!

安装Black群晖DSM7.2系统安装教程(在Vmware虚拟机中、实体机均可)!

安装 Black 群晖 DSM7.2 系统安装教程(在 Vmware 虚拟机中、实体机均可)! 前言 大家好,...
支付宝、淘宝、闲鱼又双叕崩了,Cloudflare也瘫了连监控都挂,根因藏在哪?

支付宝、淘宝、闲鱼又双叕崩了,Cloudflare也瘫了连监控都挂,根因藏在哪?

支付宝、淘宝、闲鱼又双叕崩了,Cloudflare 也瘫了连监控都挂,根因藏在哪? 最近两天的互联网堪称“故障...
如何免费使用强大的Nano Banana Pro?附赠邪修的用法

如何免费使用强大的Nano Banana Pro?附赠邪修的用法

如何免费使用强大的 Nano Banana Pro?附赠邪修的用法 前言 大家好,我是星哥,今天来介绍谷歌的 ...

免费图片视频管理工具让灵感库告别混乱

一言一句话
-「
手气不错
让微信公众号成为 AI 智能体:从内容沉淀到智能问答的一次升级

让微信公众号成为 AI 智能体:从内容沉淀到智能问答的一次升级

让微信公众号成为 AI 智能体:从内容沉淀到智能问答的一次升级 大家好,我是星哥,之前写了一篇文章 自己手撸一...
星哥带你玩飞牛NAS硬件 01:捡垃圾的最爱双盘,暴风二期矿渣为何成不老神话?

星哥带你玩飞牛NAS硬件 01:捡垃圾的最爱双盘,暴风二期矿渣为何成不老神话?

星哥带你玩飞牛 NAS 硬件 01:捡垃圾的最爱双盘,暴风二期矿渣为何成不老神话? 前言 在选择 NAS 用预...
三大开源投屏神器横评:QtScrcpy、scrcpy、escrcpy 谁才是跨平台控制 Android 的最优解?

三大开源投屏神器横评:QtScrcpy、scrcpy、escrcpy 谁才是跨平台控制 Android 的最优解?

  三大开源投屏神器横评:QtScrcpy、scrcpy、escrcpy 谁才是跨平台控制 Andr...
12.2K Star 爆火!开源免费的 FileConverter:右键一键搞定音视频 / 图片 / 文档转换,告别多工具切换

12.2K Star 爆火!开源免费的 FileConverter:右键一键搞定音视频 / 图片 / 文档转换,告别多工具切换

12.2K Star 爆火!开源免费的 FileConverter:右键一键搞定音视频 / 图片 / 文档转换...
4盘位、4K输出、J3455、遥控,NAS硬件入门性价比之王

4盘位、4K输出、J3455、遥控,NAS硬件入门性价比之王

  4 盘位、4K 输出、J3455、遥控,NAS 硬件入门性价比之王 开篇 在 NAS 市场中,威...