PHP:无法取消序列化现在实现\ Serializable接口

时间:2018-04-13 09:35:43

标签: php serialization

根据the docs

  

当现在实现此接口的类的旧实例(在类实现接口之前已经序列化)被反序列化时,将调用__wakeup()而不是unserialize方法,这可能对迁移有用。 / p>

我认为这非常聪明和有用,并希望检查出来。不幸的是它对我不起作用,我想知道是否有一些我做错了或是否有错误。

测试代码:

//class Foo
class Foo implements \Serializable
{
    public $a = 'lorem';

    public function __wakeup()
    {
        fprintf(STDOUT, "in %s\n", __METHOD__);
    }

    public function serialize()
    {
        fprintf(STDOUT, "in %s\n", __METHOD__);

        return serialize([
            $this->a,
        ]);
    }

    public function unserialize($serialized)
    {
        fprintf(STDOUT, "in %s\n", __METHOD__);

        list(
            $this->a,
        ) = unserialize($serialized);
    }
}

//$foo = new Foo();
//var_dump(serialize($foo));
//exit;

$serialised = 'O:3:"Foo":1:{s:1:"a";s:5:"lorem";}';
//$serialised = 'C:3:"Foo":22:{a:1:{i:0;s:5:"lorem";}}';

$foo = unserialize($serialised);
var_dump($foo);

它崩溃了:

Warning: Erroneous data format for unserializing 'Foo' in /in/SHaCP on line 39
Notice: unserialize(): Error at offset 13 of 34 bytes in /in/SHaCP on line 39
bool(false)

本质上,我在没有$foo接口的情况下序列化\Serializable对象。然后添加了接口并尝试unserialize()在前一个表单中序列化的对象(请注意,以O开头的序列化字符串没有接口,而以C开头的序列化字符串是接口)。

我在这里做错了吗?或许我误解了文档?

有趣的是,代码runs fine on hhvm at 3v4l.org

1 个答案:

答案 0 :(得分:0)

这是默认序列化与接口之间的主要区别 - 默认情况下,它序列化整个对象,但是通过接口的实现,您可以定义如何序列化已创建的对象'属性。

因此,由于内部实施,结果字符串将会有所不同 - 正如您在一种情况下可以看到它以" O"开头,而在另一种情况下它可以看到#& s" C"。因此,你必须再次保存它。