【问题标题】:database session handler problem数据库会话处理程序问题
【发布时间】:2011-07-25 14:27:13
【问题描述】:

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

【问题讨论】:

  • 你能确认 $sessionsData 是否有值吗?尝试在进程之前回显它。
  • var_dump 看起来很可疑。 serialize() 输出无效 - 会话数组中是否存储了任何可能被浏览器视图“隐藏”的 HTML/xml?你在浏览器的 view-source 中看到了什么?
  • @Marc B:var_dump 看起来非常适合会话数据。 serialize() 不能与会话数据一起正常工作,我认为您将其混为一谈,因为它很接近,但会话数据是 a list of variable names with their serialized values,就像 ({varname}|{serialized($varname)})* 一样。
  • serialize() 不在乎它的会话数据。它只是另一个数据结构,基本上是serialize($_SESSION)。一个有效的序列化会话数组至少以a:... 开头。 | 不是有效的分隔符。
  • @Marc B:你最好自己试试,函数不是serialize(),而是session_encode()。阅读该手册页最上面的注释。

标签: php mysql session handler


【解决方案1】:

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

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

public function Read($sessionsId)

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

但是您返回的是一个数组(看起来 - 不能具体说明,因为实际的数据库是隐藏的,PDO/MySQLi?)。

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

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


除此之外,我怀疑是一种编码问题,但我不完全确定这是导致它的原因。但只需考虑以下几点:

会话数据是二进制数据,而不是文本。您可以更改表定义并相应地访问。在 MySQL 中有 BLOB Type 用于此,bindParam() 可以使用 PDO::PARAM_LOB 数据类型说明符。

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

【讨论】:

  • @hackre:将模式更改为 BLBO 类型我已经尝试过您的建议无效,我在该字段中得到 [BLOB - 0octețs]。
  • @silent for the echo:会话 ID 为:lhig71coed8ur81n85iiovje37 会话 ID 的值为:name|s:6:"Bogdan"; on var_dump string(18) "name|s:6:"Bogdan";" string(26) "lhig71coed8ur81n85iiovje37" on print_r name|s:6:"Bogdan"; lhig71coed8ur81n85iiovje37 这三个都是函数函数写入所以我得到数据直到那一步是肯定的。在第一篇文章中,我在那里吃了一些信,我很抱歉有点饿,但我现在吃了点东西。至于源代码,我看不出有什么问题@hakre,感谢您为该文档添加书签并仍在阅读。
  • @Bogdan:我明白了,但我认为您仍然应该坚持使用 BLOB 而不是文本来将数据(当它工作时)存储为二进制而不是文本。
  • @hrake 我会采纳你的建议并使用它:)
  • @Bogdan:我可能找到了罪魁祸首,请参阅编辑后的答案。
猜你喜欢
  • 1970-01-01
  • 2012-11-08
  • 1970-01-01
  • 2015-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-28
相关资源
最近更新 更多