以下是关于session_set_save_handler()函数的详细讲解及用法示例:
一、函数语法解析
1. 传统回调函数形式(PHP 5.4前)
bool session_set_save_handler( callable $open, // 初始化存储 callable $close, // 关闭存储 callable $read, // 读取数据 callable $write, // 写入数据 callable $destroy, // 销毁会话 callable $gc, // 垃圾回收 [callable $create_sid] // 可选:生成自定义ID )
参数说明:
open(string $savePath, string $sessionName):会话开始时触发,用于建立存储连接read(string $sessionId):返回指定ID的会话数据(需反序列化)write(string $sessionId, string $data):写入序列化后的会话数据gc(int $maxlifetime):清理过期会话记录
2. 面向对象形式(PHP 5.4+)
bool session_set_save_handler( SessionHandlerInterface $handler, bool $register_shutdown = true )
特点:
需实现
SessionHandlerInterface接口的6个方法register_shutdown参数决定是否自动注册关闭函数(默认启用)
二、核心用法示例
示例1:数据库存储会话(面向对象式)
class DBSessionHandler implements SessionHandlerInterface {
private $pdo;
public function open($savePath, $sessionName) {
$this->pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
return true;
}
public function read($sessionId) {
$stmt = $this->pdo->prepare("SELECT data FROM sessions WHERE id=?");
$stmt->execute([$sessionId]);
return $stmt->fetchColumn() ?: '';
}
// 其他方法实现...
}
// 注册处理器
$handler = new DBSessionHandler();
session_set_save_handler($handler, true); // 自动关闭
session_start();关键点:
数据库表需包含
id(主键)、data(会话数据)、last_accessed(时间戳)字段write()方法应使用REPLACE INTO语句确保数据覆盖
示例2:解决文件锁阻塞问题
session_set_save_handler(
function() { return true; }, // open
function() { return true; }, // close
function($id) { return ''; }, // read
function($id, $data) { return true; }, // write
function($id) { return true; }, // destroy
function($maxLife) { return true; } // gc
);
register_shutdown_function('session_write_close'); // 手动注册关闭
session_start();作用:避免默认文件存储的独占锁导致请求阻塞
三、关键参数register_shutdown详解
典型问题:
设置为
false且未手动关闭时,异常退出会导致数据丢失异步任务中建议显式调用
session_write_close()释放资源
四、完整调用流程
初始化阶段
session_start()→open()→read()→ 填充$_SESSION运行阶段
修改$_SESSION后触发write()(脚本结束或显式调用session_write_close())销毁阶段
session_destroy()→destroy()→ 删除存储数据
五、注意事项
调用顺序
必须在session_start()前设置处理器,否则无效分布式系统
需确保所有节点使用相同的存储后端和ID生成规则安全建议
启用
session.use_strict_mode防止会话固定攻击定期调用
session_regenerate_id()更新会话ID