您好我正在尝试了解会话如何工作以及session_set_handler()
如何工作,所以我开始构建一个会话处理类,但我遇到了write()
函数的一些问题你能帮我解决一下这个问题吗?
<?php
class Session extends Model
{
public
$connectionName = 'sessions',
$sessionsId,
$sessionsData;
public function __construct()
{
parent::__construct();
session_set_save_handler(
array($this, 'Open'),
array($this, 'Close'),
array($this, 'Read'),
array($this, 'Write'),
array($this, 'Destroy'),
array($this, 'Gc'));
session_start();
}
public function __destruct()
{
session_write_close();
}
public function Open()
{
return true;
}
public function Close()
{
return true;
}
public function Read($sessionsId)
{
$this->stmt = $this->prepare("SELECT * FROM `sessions` WHERE `id` = :sessionId");
$this->stmt->bindParam(":sessionId", $sessionsId);
$this->stmt->execute();
return $this->stmt->fetchAll();
}
public function Write($sessionsId, $sessionsData)
{
$this->stmt = $this->prepare("REPLACE INTO `sessions`.`sessions`
(`id`, `access`, `data`)
VALUES
(:sessionId, NOW(), :sessionValue)");
$this->stmt->bindParam(":sessionId", $sessionsId);
$this->stmt->bindParam(":sessionValue", $sessionsData);
$this->stmt->execute();
}
public function Destroy($sessionsId)
{
$this->stmt = $this->prepare("DELETE FROM `sessions`.`sessions` WHERE `id` = :sessionId");
$this->stmt->bindParam(":sessionId", $sessionsId);
$this->stmt->execute();
}
public function Gc()
{
$this->stmt = $this->prepare("DELETE FROM `sessions`.`sessions` WHERE `access` < NOW() - INTERVAL 1 HOUR");
$this->stmt->execute();
}
}
现在上面的代码似乎工作得很好唯一的问题是当我在db中编写会话时我得到以下插入:
从mysql转储
CREATE TABLE IF NOT EXISTS `sessions` (
`id` varchar(32) NOT NULL,
`access` datetime NOT NULL,
`data` text NOT NULL,
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `sessions` (`id`, `access`, `data`) VALUES
('lhig71coed8ur81n85iiovje37', '2011-07-25 15:37:57', '');
正如你可以看到它未插入的会话值我只得到会话ID。
在var_dump($sessionsData)
我得到:
"name|s:6:"Bogdan";"
和var_dump($sessionsId)
我得到:
lhig71coed8ur81n85iiovje37
你能帮帮忙吗?我没有得到任何错误检查xampp日志设置显示错误报告错误报告所有我知道甚至在php.ini仍然没有错误任何使用甚至尝试catch块。非常感谢你阅读并帮助我。
答案 0 :(得分:1)
我在您的实施中发现了一个缺陷,导致删除任何会话数据:
return $this->stmt->fetchAll();
in
public function Read($sessionsId)
该函数必须返回一个字符串,在您的情况下是data
字段中的数据。
但是你要返回一个数组(看起来像 - 不能特别说因为实际数据库是隐藏的,PDO / MySQLi?)。
然而,反序列化会话数据(请参阅session_decode()
)很可能会失败,因此会话数据将变为空,然后再次保存(作为空字符串)。
这应该是您的问题的原因。通过从数据库返回字符串数据来修复它。
接下来我怀疑是一种编码问题,但我并不完全确定这会导致它。但请考虑以下几点:
会话数据是二进制数据,而不是文本。您可以相应地更改表定义和访问权限。在MySQL中有BLOB
Type,bindParam()
可以帮助PDO::PARAM_LOB
数据类型说明符。
这种类型的改变可能会解决您的问题。否则,它将确保您存储未经修改的数据,这在任何情况下都是您想要的。坚持对会话数据进行二进制安全处理。