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

Car*_*los 8 php persistence pdo pdostatement

您好我想在会话中存储或保存一个对象,使用类如SessionHandler或数组$ _SESSION,我已经看到,如果我序列化该对象,我可能不会丢失该对象的方法实例..我已经看到seralizing它是可能的,但我想要存储的对象是由PDOStatement :: fetchObject()创建的,虽然实例类是"Users"我得到这个错误:

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

对不起,我是西班牙人,我不会说英语.谢谢

Fra*_*ila 14

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

PHP无法序列化,resources因为它们是PHP控件之外的某些有状态资源的句柄.这就是您无法序列化PDOPDOStatement对象的原因.

默认情况下,通过保存所有属性名称和值来序列化对象,并通过创建具有相同类的对象(不调用构造函数)并直接设置序列化属性来反序列化.您可以使用__sleepand __wakeupmagic方法或通过实现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;
Run Code Online (Sandbox Code Playgroud)

现在想象你改变Test一天就是这样:

class Test {
    public $version = 2;
    private $def;
    public function setDef ($def) {
        $this->def = $def;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在假设您在新代码中加载了Test版本1 时序列化的对象:

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

var_dump($t)
Run Code Online (Sandbox Code Playgroud)

你会得到这个:

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

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

if ($t->version == 1) { // Check for class version
    $t->setAbc(345); // "Fatal error: Call to undefined method Test::setAbc()"
}
Run Code Online (Sandbox Code Playgroud)

  • 这在答案中解释.构造函数未执行,因为对象被*恢复*不*初始化*.创建一个`__wakeup()`或`Serializer`接口`unserialize()`方法,它可以做你想要的,或者添加一个`setPDO()`方法并手动设置PDO对象.但是,最重要的是,**你不应该序列化包含资源的对象**!使用不同的班级设计. (3认同)