【问题标题】:Return value of SessionHandlerInterface methods in PHPPHP中SessionHandlerInterface方法的返回值
【发布时间】:2021-06-17 19:35:55
【问题描述】:

我试图了解 PHP 会话处理程序,更准确地说是 SessionHandlerInterface::read 的返回值。

The doc 状态(强调我的):

返回读取数据的编码字符串。 如果没有读取任何内容,则必须返回 false。请注意,此值在内部返回给 PHP 进行处理。

但是,the documentation of the SessionHandler class 和其他实现中使用的示例(例如 Symfony 的 PdoSessionHandler)似乎在无法读取任何内容时(例如第一次连接到主机时)返回一个空字符串。

为了说明这一点,我编写了一个简单的测试(该类继承自SessionHandler,而不是实现整个SessionHandlerInterface,为了简单起见——我知道不推荐这样做,而且这个例子也没用:它只是为了显示问题):

<?php

define('RETURN_VALUE', false);

class SimpleSessionHandler extends SessionHandler
{
    public function read($id)
    {
        $data = parent::read($id);

        if (!$data) {
            return RETURN_VALUE;
        } else {
            return data;
        }
    }
}

$handler = new SimpleSessionHandler();
session_set_save_handler($handler, true);
$res = session_start();
print_r($res);
echo("Done");

当使用 false 作为返回值时,我得到一个 PHP 错误 (Warning: session_start(): Failed to read session data),而当我使用 ''(空字符串)时,它就像一个魅力。

我错过了什么?

我在 Fedora 33 下使用 PHP 7.4.20。

【问题讨论】:

  • docs of SessionHandler 还说:“警告该类旨在公开当前内部 PHP 会话保存处理程序,如果您想编写自己的自定义保存处理程序,请实现 SessionHandlerInterface 接口而不是从 SessionHandler 扩展”。但是我认为没有必要返回您自己的值,您也可以return parent::read($id);
  • 除了我的第一条评论之外,我得出的结论是,继承类并一对一地采用覆盖方法是没有意义的。因此,您的 SimpleSessionHandler 类在其当前格式下没有任何意义。需要自定义会话处理程序还有其他原因,例如在数据库中存储会话时。
  • 正如我所说,这个例子是为了说明:它没有任何用处,我选择从 SessionHandler 继承,尽管文档为了简单起见(否则,代码将是 5 次)更长)。这是基于SessionHandlerInterface 的尝试的简化版本来显示问题。我会说得更清楚。
  • 如上所述,If nothing was read, it must return false 从这里我认为这意味着,如果会话文件未打开或文件不可读或在这种情况下抛出任何错误/异常read 方法应该返回 false,但是如果文件已打开且可读但为空,则应返回 empty 字符串而不是 false
  • 这是我的预期,但问题是您第一次连接时,会话文件不存在。所以按照文档,我们应该返回 false 但在这种情况下,PHP 不会打开会话。

标签: php session


【解决方案1】:

我在 PHP 邮件列表上提出了问题(请参阅线程 here)。

据我了解,read() 应该尝试读取数据(如果存在),如果不存在则返回空字符串;仅当它无法读取数据时(例如,如果无法创建或读取会话文件,如果无法访问数据库等),它应该返回 false。

对于基于某个数据库的会话处理程序,它会是这样的:

<?php

class DBSessionHandler implements SessionHandlerInterface
{
    public function read($id)
    {
        try {
            $data = $this->get_session_from_db();
            if (len($data) > 0) {
                // Return data
                $this->serialize($data);
            } else {
                // Create new empty session here
                try {
                    $this->create_empty_session_in_db();
                } catch (Exception $e) {
                    return false;
                }
                return '';
            }
        } catch (Exception $e) {
            return false;
        }
    }
}

我猜大多数处理程序会延迟插入 write()

【讨论】:

    猜你喜欢
    • 2015-10-16
    • 2012-11-19
    • 1970-01-01
    • 2019-05-10
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 2014-10-18
    相关资源
    最近更新 更多