【问题标题】:How can I store objects in a session in PHP?如何在 PHP 的会话中存储对象?
【发布时间】:2012-10-30 23:09:05
【问题描述】:

您好,我想在会话中存储或保存对象,使用 SessionHandler 或数组 $_SESSION 等类,我已经看到如果我序列化对象是可能的,我不想丢失方法那个对象实例的.. 我已经看到序列化它是可能的,但是我想要存储的对象是由 PDOStatement::fetchObject() 创建的,尽管实例类是“用户”我收到这个错误:

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

对不起,我是西班牙人,我的英语不太好.. 谢谢

【问题讨论】:

  • 显示您是如何尝试序列化它的,从异常看来您正在尝试序列化语句,而不是结果。
  • @dev-null-dweller 所说的。我可以序列化PDOStatement::fetchObject的结果就好了。
  • 如果对象来自数据库,为什么要在会话中序列化它?只需再次从数据库中获取它。应尽可能避免会话。

标签: php pdo persistence pdostatement


【解决方案1】:

PHP 的原生 $_SESSION 会话透明地序列化和反序列化支持 PHP 的 serialization protocolSerializable interface 的对象。您不需要显式序列化它们。

PHP 无法序列化resources,因为这些是PHP 无法控制的一些有状态资源的句柄。这就是你不能序列化PDOPDOStatement 对象的原因。

默认情况下,通过保存所有属性名称和值来序列化对象,并通过创建具有相同类的对象(不调用构造函数)并直接设置序列化属性来取消序列化。您可以使用__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()"
}

【讨论】:

  • 谢谢它解决了我的问题,但是我有一个新问题,在那个类上,我在 __constructor(连接到 MySQL)中传递了 PDO 对象,并将一个成员变量设置为 PDO 对象,但是当我反序列化“容器对象”它不执行__constructor函数,所以不会设置作为PDO对象的成员变量..我该如何解决?谢谢
  • 答案中对此进行了解释。构造函数未执行,因为对象已恢复而不是初始化。创建一个__wakeup()Serializer 接口unserialize() 方法来执行您想要的操作,或者添加一个setPDO() 方法并手动设置PDO 对象。不过,底线是,您不应该序列化包含资源的对象!使用不同的类设计。
  • 非常感谢,我喜欢你添加 setPDO 方法的想法,你是对的 :)
猜你喜欢
  • 2017-12-06
  • 2012-01-26
  • 2011-01-03
  • 1970-01-01
  • 2011-07-31
  • 1970-01-01
  • 2017-08-25
相关资源
最近更新 更多