【发布时间】:2011-11-17 08:12:22
【问题描述】:
在数据库中存储会话时,我注意到更新会话不一定会调用 session_set_save_handler() 中设置的写入函数。当您在脚本末尾调用 session_write_close() 时,这个问题似乎得到了解决。
使用 session_set_save_handler() 将会话存储在数据库中时,我是否遗漏了什么?
我当前使用的代码。
// EXECUTE AT START OF SCRIPT
$session = new Session();
session_start();
会话类
public function __construct() {
$database = Database::instance();
$this->dbh = $database->dbh();
$this->lifetime = get_cfg_var('session.gc_maxlifetime');
session_set_save_handler(
array(&$this, 'open'),
array(&$this, 'close'),
array(&$this, 'read'),
array(&$this, 'write'),
array(&$this, 'destroy'),
array(&$this, 'clean')
);
}
// SESSION HANDLER METHODS
function open($savePath, $sessionName) {
return true;
}
function close() {
return true;
}
function read($sessionUuid) {
logMessage('READ SESSION DATA > ' . $sessionUuid);
$data = array();
$time = time();
$sth = $this->dbh->prepare("SELECT sessionData FROM phpSession WHERE sessionUuid = :sessionUuid AND expires > " . $time);
$sth->setFetchMode(PDO::FETCH_ASSOC);
try {
$sth->execute(array('sessionUuid' => $sessionUuid));
if ($sth->rowCount() == 1) {
$row = $sth->fetch();
$data = $row['sessionData'];
}
} catch (PDOException $exception) {
// HANDLE EXCEPTION
}
return $data;
}
function write($sessionUuid, $sessionData) {
logMessage('WRITE SESSION DATA > ' . $sessionUuid);
$time = time() + $this->lifetime;
$sth1 = $this->dbh->prepare("SELECT sessionUuid FROM phpSession WHERE sessionUuid = :sessionUuid");
try {
$sth1->execute(array('sessionUuid' => $sessionUuid));
$query = '';
$data = array(
'sessionUuid' => $sessionUuid,
'sessionData' => $sessionData,
'expires' => $time
);
if ($sth1->rowCount() == 1) {
// UPDATE
$query = "UPDATE phpSession SET sessionUuid = :sessionUuid, sessionData = :sessionData, expires = :expires";
} else {
// INSERT
$query = "INSERT INTO phpSession (sessionUuid, sessionData, expires) VALUES (:sessionUuid, :sessionData, :expires)";
}
$sth2 = $this->dbh->prepare($query);
try {
$sth2->execute($data);
} catch (PDOException $exception) {
// HANDLE EXCEPTION
}
} catch (PDOException $exception) {
// HANDLE EXCEPTION
}
return true;
}
function destroy($sessionUuid) {
$sth = $this->dbh->prepare("DELETE FROM phpSession WHERE 'sessionUuid' = :sessionUuid");
try {
$sth->execute(array('sessionUuid' => $sessionUuid));
} catch (PDOException $exception) {
// HANDLE EXCEPTION
}
return true;
}
function clean() {
$sth = $this->dbh->prepare("DELETE FROM phpSession WHERE 'expires' < UNIX_TIMESTAMP()");
try {
$sth->execute();
} catch (PDOException $exception) {
// HANDLE EXCEPTION
}
return true;
}
【问题讨论】:
-
只是对您的班级的一个小提示,而不是问题(您有答案):在最后两种方法(销毁和清理)中,我看到您将列名包含在查询之间撇号而不是反引号。这对你有用吗?
-
感谢您的评论。到目前为止,我没有遇到任何使用撇号的问题。
-
我不记得这条评论,但我仍然觉得奇怪的是,您在列名中使用了撇号。取这两个样本:codepad.org/n7mOQz5h 和 codepad.org/NeY7a7nn 第一个来自您的
destroy方法,第二个用反引号替换撇号。第一个(您的)会将字符串“sessionUuid”与会话 ID 进行比较,并且始终为假。第二个会将该列的值与参数进行比较,有时会匹配行。您可以运行测试,您将看到使用您的查询没有删除任何记录