php.net 手册的session_set_save_handler
示例是基于文件的。我试图为mysql实现它。
我在 Windows 中使用uniserver 。我的错误显示设置是开发环境。
我的问题是我无法让垃圾收集功能自动工作。我没有收到错误/警告。我所有的相关代码都在下面。
我的意思是:如果我$handler->gc($maxlifetime);
在会话测试后在 index.php 中使用它,它会起作用并删除过期的行。
如果我不在$handler->gc($maxlifetime);
index.php 中使用,则会保留过期的行。
我的问题
q1 - 我应该$handler->gc($maxlifetime);
在 index.php 中使用吗?
q2 - 如果对 q1 的回答是肯定的,为什么回调函数有一个gc
函数。
q3$handler->gc($maxlifetime);
- 如果对 q1 的回答是否定的,为什么在我关闭浏览器(ie11)、刷新 index.php 并检查我的 mysql 会话表后,我的过期行没有被删除(以防我在 index.php 中没有)?请注意,这$maxlifetime
是 1(秒)。
谢谢,最好的问候
我的 index.php
// populate inclusion paths
...
// mysql PDO connect
require_once("config.php");
$dbh = new PDO("mysql:host=$my_host;dbname=$my_db;charset=utf8", $my_username, $my_password);
// start session
require_once("class_Session.php");
$maxlifetime = 1; // seconds
$handler = new MySessionHandler($dbh, $maxlifetime);
session_set_save_handler(
array($handler, 'open'),
array($handler, 'close'),
array($handler, 'read'),
array($handler, 'write'),
array($handler, 'destroy'),
array($handler, 'gc')
);
// the following prevents unexpected effects when using objects as save handlers
register_shutdown_function('session_write_close');
session_start();
$_SESSION['user'] = 'joe';
if (isset($_SESSION['user'])) { echo $_SESSION['user']; }
// note if I try code below, expired rows are deleted
// $handler->gc($maxlifetime);
// some other irrelevant-to-this case codes
...
// close mysql connection
$dbh = NULL;
MySessionHandler 类
class MySessionHandler {
private $_db;
private $maxlifetime;
function __construct(PDO $dbh, $maxlifetime)
{
$this->_db = $dbh;
$this->maxlifetime = $maxlifetime;
return (TRUE);
}
function open()
{
}
function close()
{
$this->_db = NULL;
return (TRUE);
}
function read($id)
{
$query = "SELECT `data` FROM `sessions` WHERE id = ? LIMIT 1";
$this->read_stmt = $this->_db->prepare($query);
$this->read_stmt->bindParam(1, $id, PDO::PARAM_STR);
$this->read_stmt->execute();
$data = $this->read_stmt->fetchColumn();
return $data;
}
function write($id, $data)
{
$query = "REPLACE `sessions` (`id`, `data`) VALUES(?,?)";
$this->w_stmt = $this->_db->prepare($query);
$this->w_stmt->bindParam(1, $id, PDO::PARAM_STR);
$this->w_stmt->bindParam(2, $data, PDO::PARAM_STR);
$this->w_stmt->execute();
return (TRUE);
}
function destroy($id)
{
$query = "DELETE FROM `sessions` WHERE id = ?";
$this->delete_stmt = $this->_db->prepare($query);
$this->delete_stmt->bindParam(1, $id, PDO::PARAM_STR);
$this->delete_stmt->execute();
return (TRUE);
}
function gc($maxlifetime)
{
// instead of CURRENT_TIMESTAMP(), I also tried NOW() command
$query = "DELETE FROM `sessions` WHERE `update_time` < CURRENT_TIMESTAMP() - INTERVAL ? SECOND";
$this->gc_stmt = $this->_db->prepare($query);
$this->gc_stmt->bindParam(1, $this->maxlifetime, PDO::PARAM_STR);
$this->gc_stmt->execute();
return (TRUE);
}
}
会话表的相关 SQL
CREATE TABLE `sessions`
(
`id` CHAR(32) NOT NULL,
`data` BLOB,
`update_time` TIMESTAMP NOT NULL,
PRIMARY KEY (id),
INDEX (update_time)
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_unicode_ci;