PHP 中的 session_set_save_handler() 函数可以设置自定义的会话存储函数,通过这些自定义函数来操作 Session,从而将 Session 信息存储到数据库中。session_set_save_handler() 函数有两种形式,其语法格式如下:
session_set_save_handler(
callable $open,
callable $close,
callable $read,
callable $write,
callable $destroy,
callable $gc
[, callable $create_sid
[, callable $validate_sid
[, callable $update_timestamp]]]
)
参数说明如下:
- $open(string $savePath, string $sessionName):$open 回调函数类似于类的构造函数,在会话打开的时候会被自动调用。这是自动开始会话或者通过调用 session_start() 手动开始会话之后第一个被调用的回调函数。此回调函数操作成功会返回 TRUE,反之返回 FALSE;
- $close():$close 回调函数类似于类的析构函数。 在 $write 回调函数调用之后调用。当调用 session_write_close() 函数之后,也会调用 $close 回调函数。此回调函数操作成功返回 TRUE,反之返回 FALSE;
- $read(string $sessionId):如果会话中有数据的话,$read 回调函数会返回 $sessionId 所对应的 Session 数据;如果会话中没有数据,那么 $read 回调函数会返回空字符串。在会话自动开始或者通过调用 session_start() 函数手动开始会话之后,PHP 会在内部调用 $read 回调函数来获取会话数据。在调用 $read 之前,PHP 会调用 $open 回调函数;
- $write(string $sessionId, string $data):在创建或修改 Session 信息时会调用 $write 回调函数。此回调函数接收当前会话的 ID 以及 $_SESSION 中数据序列化之后的字符串作为参数。序列化会话数据是由 PHP 根据 session.serialize_handler 设定值来自动完成;
- $destroy($sessionId):当调用 session_destroy() 函数或者调用 session_regenerate_id() 函数并且设置 $destroy 参数为 TRUE 时,会调用此回调函数。此回调函数操作成功返回 TRUE,反之返回 FALSE;
- $gc($lifetime):为了清理会话中的旧数据,PHP 会不时的调用垃圾收集回调函数。调用周期由 session.gc_probability 和 session.gc_divisor 参数控制。传入到此回调函数的 $lifetime 参数由 session.gc_maxlifetime 设置。此回调函数操作成功返回 TRUE,反之返回 FALSE;
- $create_sid():可选参数,当需要新的会话 ID 时被调用的回调函数。回调函数被调用时不用传入参数,其返回值应该是一个字符串格式的、有效的会话 ID;
- $validate_sid():可选参数,用来验证会话 ID;
- $update_timestamp():可选参数,用来修改时间戳。
除了上面这种形式,session_set_save_handler() 函数还有另外一种形式(自 PHP5.4 及以上版本可用),如下所示:
session_set_save_handler(object $sessionhandler [, bool $register_shutdown = TRUE])
参数说明如下:
- $sessionhandler:实现了 SessionHandlerInterface、SessionIdInterface 或 SessionUpdateTimestampHandlerInterface 接口的对象,例如 SessionHandler;
- $register_shutdown:可选参数,将函数 session_write_close() 注册为 register_shutdown_function() 函数。
一般函数的参数都是直接使用变量,但是 session_set_save_handler() 函数中却是以多个函数的名称作为参数。下面将通过示例的形式对这几个参数(函数)分别进行讲解。
1) 封装 sess_open() 函数,用来连接数据库,示例代码如下:
<?php // 连接数据库 function sess_open($savePath, $sessionName){ global $link; $link = mysqli_connect('localhost', 'root', 'root') or die('数据库连接失败!'); mysqli_select_db($link, 'testdb') or die('未找到该数据库!'); return true; } ?>
函数中并没有用到 $save_path 和 $session_name 这两个参数,可以将它们去掉,但是建议读者保留这两个参数,因为一般使用时都是存在这两个变量的,应该养成一个好的习惯。
2) 封装 sess_close() 函数,用来关闭数据库连接,示例代码如下:
<?php // 关闭数据库连接 function sess_close(){ global $link; mysqli_close($link); return true; } ?>
在这个函数中不需要任何参数,所以不论是将 Session 存储到数据库还是文件中,都只需返回 true 即可。但是这里是将 Session 存储到数据库中,所以最好还是在这里将数据库关闭,以避免出现其它问题。
3) 封装 sess_read() 函数,根据参数 $sessionId 来获取 Session 的信息,示例代码如下:
<?php // 读取 Session 内容 function sess_read($sessionId){ global $link; $time = time(); $sql = "SELECT data FROM session WHERE id = '$sessionId' AND lapse_time > '$time'"; $result = mysqli_query($link, $sql); $row = mysqli_fetch_array($result, MYSQLI_ASSOC); if($row){ return $row['data']; }else{ return false; } } ?>
4) 封装 sess_write() 函数,用来将 Session 内容写入数据库,示例代码如下:
<?php // 写入 Session function sess_write($sessionId, $data){ global $link; $lapse_time = time()+(60*60); $sql = "SELECT data FROM session WHERE id = '$sessionId'"; $result = mysqli_query($link, $sql); if(mysqli_num_rows($result) == 0){ $ins_sql = "INSERT INTO session VALUES('$sessionId', '$data', '$lapse_time')"; $res = mysqli_query($link, $ins_sql); }else{ $up_sql = "UPDATE session SET data = '$data', lapse_time = '$lapse_time' WHERE id = '$sessionId'"; $res = mysqli_query($link, $up_sql); } return $res; } ?>
5) 封装 sess_destroy() 函数,用来删除指定的 Session 数据,示例代码如下:
<?php // 删除 Session function sess_destroy($sessionId){ global $link; $sql = "DELETE FROM session WHERE id = '$sessionId'"; return mysqli_query($link, $sql); } ?>
6) 封装 sess_gc() 函数,用来清理失效的 Session,示例代码如下:
<?php // 清理失效的 Session function sess_gc(){ global $link; $time = time(); $sql = "DELETE FROM session WHERE lapse_time < '$time'"; $res = mysqli_query($link, $sql); return $res; } ?>
以上定义的 6 个函数便是 session_set_save_handler() 函数 6 个必选参数,调用 session_set_save_handler() 函数即可实现将 Session 存储到数据库中,示例代码如下:
<?php ini_set("session.save_handler", "user"); session_set_save_handler('sess_open', 'sess_close', 'sess_read', 'sess_write', 'sess_destroy', 'sess_gc'); session_start(); $_SESSION['user'] = 'admin'; ?>
运行上面的代码即可将 user = 'admin' 的 Session 信息写入到数据库,如下所示:
mysql> SELECT * FROM session;
+——————————–+——————-+————–+
| id | data | lapse_time |
+——————————–+——————-+————–+
| c91mct86sfs3gs9lpke225b8ir | user|s:5:"admin"; | 1595587392 |
+——————————–+——————-+————–+
1 row in set (0.00 sec)
上面代码中 ini_set("session.save_handler", "user"); 用来临时修改 PHP 的配置信息,与直接将 php.ini 配置文件中 session.save_handler 的值改为 user 效果相同。另外需要注意的是,以上代码仅在 PHP7.0 版本中成功运行,其它版本暂未测试通过。
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/23998.html