数据库会话处理问题

时间:2011-07-25 14:27:14

标签: php mysql session handler

您好我正在尝试了解会话如何工作以及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块。非常感谢你阅读并帮助我。

1 个答案:

答案 0 :(得分:1)

我在您的实施中发现了一个缺陷,导致删除任何会话数据:

return $this->stmt->fetchAll();

in

public function Read($sessionsId)

该函数必须返回一个字符串,在您的情况下是data字段中的数据。

但是你要返回一个数组(看起来像 - 不能特别说因为实际数据库是隐藏的,PDO / MySQLi?)。

然而,反序列化会话数据(请参阅session_decode())很可能会失败,因此会话数据将变为空,然后再次保存(作为空字符串)。

这应该是您的问题的原因。通过从数据库返回字符串数据来修复它。


接下来我怀疑是一种编码问题,但我并不完全确定这会导致它。但请考虑以下几点:

会话数据是二进制数据,而不是文本。您可以相应地更改表定义和访问权限。在MySQL中有BLOB TypebindParam()可以帮助PDO::PARAM_LOB数据类型说明符。

这种类型的改变可能会解决您的问题。否则,它将确保您存储未经修改的数据,这在任何情况下都是您想要的。坚持对会话数据进行二进制安全处理。