如何在 PHP 中的会话中存储对象?

问题描述 投票:0回答:1

您好,我想使用像

SessionHandler
或数组 $_SESSION 这样的类在会话中存储或保存对象,我已经看到如果我序列化该对象是可能的,并且我不想丢失这些方法该对象实例的。 我已经看到序列化是可能的,但我想要存储的对象是由 PDOStatement::fetchObject() 创建的,尽管实例类是
Users
我收到此错误:

PDOException:您无法序列化或反序列化 PDO 实例 为什么?它不是 PDO 实例..

抱歉,我是西班牙人,英语说得不太好.. 谢谢

php persistence pdo
1个回答
15
投票

PHP 的本机

$_SESSION
会话透明地序列化和反序列化支持 PHP 序列化协议
Serializable
接口
的对象。您不需要显式序列化它们。

PHP 无法序列化

resources
,因为这些是 PHP 控制之外的某些有状态资源的句柄。这就是为什么您无法序列化
PDO
PDOStatement
对象。

默认情况下,通过保存所有属性名称和值来序列化对象,并通过创建具有相同类的对象(不调用构造函数)并直接设置序列化属性来反序列化。您可以使用

__sleep
__wakeup
魔术方法或通过实现
Serializable
接口来自定义对象的序列化行为。但两者都不是!如果您使用
implements Serializable
,则
__sleep
__wakeup
将被忽略。

一个重要注意事项:使用对象序列化时,必须在反序列化之前加载类定义(或具有可以加载它的自动加载器),并且它必须与被序列化的对象的类定义匹配。类定义不存储在序列化数据中。

例如,假设您有以下内容:

class Test {
    public $version = 1;
    protected $abc;
    public function setAbc($abc) {
        $this->abc = $abc;
    }
}

$t = new Test();
$t->setAbc(123);
$_SESSION['mytest'] = $t;

现在想象一下有一天你改变

Test
变成这样:

class Test {
    public $version = 2;
    private $def;
    public function setDef ($def) {
        $this->def = $def;
    }
}

现在假设您将

Test
处于版本 1 时序列化的对象加载到新代码中:

$t = $_SESSION['mytest']; // this was stored yesterday, when Test was version 1

var_dump($t)

你会得到这个:

object(Test)#1 (3) {
  ["version"]=>
  int(1)
  ["def":"Test":private]=>
  NULL
  ["abc":protected]=>
  int(123)
}

此外,你不能使用旧方法:

if ($t->version == 1) { // Check for class version
    $t->setAbc(345); // "Fatal error: Call to undefined method Test::setAbc()"
}
© www.soinside.com 2019 - 2024. All rights reserved.