如何正确使用PDO::FETCH_SERIALIZE?

How to use PDO::FETCH_SERIALIZE correctly?

我尝试实现使用 PDO::FETCH_SERIALIZE 自动反序列化数据库中的 php 对象的代码。

我已经检查了文档和 corresponding php test,它看起来与我所拥有的基本相同:

class foo implements Serializable {
    private $data;
    public function __construct() {
        $this->data = "My private data";
    }
    public function serialize() {
        return serialize($this->data);
    }
    public function unserialize($data) {
        $this->data = unserialize($data);
    }
    public function getData() {
        return $this->data;
    }
}
$foo = new foo;

$stmt = $pdo->prepare('SELECT \'C:3:"foo":23:{s:15:"My private data";}\' foo');
$stmt->execute();
$stmt->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_SERIALIZE, 'foo');
$data = $stmt->fetch();
var_dump($data);

但它仍然将其反序列化为不符合预期的东西。这段代码运行ning的结果是

object(foo)#4 (1) {
  ["data":"foo":private]=>
  object(foo)#5 (1) {
    ["data":"foo":private]=>
    string(15) "My private data"
  }
}

而人们不会期望对象是嵌套的。应该是

object(foo)#2 (1) {
  ["data":"foo":private]=>
  string(15) "My private data"
}

相反。

我错过了什么?

UPD 1:

我只是尝试使用真实的 table 而不是硬编码数据。它没有任何改变。当前的代码经过精心设计,因此每个人都可以 运行 它而无需创建测试 database/tables 来检查它。

UPD 2:

别名没有任何变化,实际上可以完全省略。

UPD 3:

我创建了一个错误 https://bugs.php.net/bug.php?id=68802,让我们看看 php 开发团队是否接受它。

您正在手工制作的查询中序列化整个对象。

$stmt = $pdo->prepare('SELECT \'C:3:"foo":23:{s:15:"My private data";}\' foo');

应该是:

$stmt = $pdo->prepare('SELECT \'s:15:"My private data";\' foo');

仅仅因为 foo::serialize returns s:15:"My private data"; 而不是整个序列化对象,稍后,相同的序列化字符串被注入 foo::unserialize,因此在您的情况下,$data instanceof foo 而不是字符串。

如您所料的输出:

object(foo)#4 (1) {
  ["data":"foo":private]=>
  string(15) "My private data"
}