添加可序列化接口

时间:2019-02-16 15:28:24

标签: php oop serialization

我有一个使用serialize()存储在MySql中的对象。

现在,我通过使其实现Serializable接口来更新类定义,并且由于以下原因,我无法反序列化对象:

Erroneous data format for unserializing 'ClassName'

此类的调试方法unserialize()无济于事-甚至没有调用。

仅作为示例,假设我有类的旧(A)和新(B)声明:

<?php

 class A {
     public $hello = "world";
 }

  class B implements Serializable {
     public $hello = "world";
     public function serialize() {}
     public function unserialize($serialized) { throw new Exception("test"); }
 }

现在当我尝试反序列化数据时:

$data1 = 'O:1:"A":1:{s:5:"hello";s:5:"world";}';
$data2 = 'O:1:"B":1:{s:5:"hello";s:5:"world";}';

var_dump(unserialize($data1));
var_dump(unserialize($data2));

我明白了

object(A)#2 (1) {
  ["hello"]=>
  string(5) "world"
}
<br />
<b>Warning</b>:  Erroneous data format for unserializing 'B' in <b>[...][...]</b> on line <b>20</b><br />
<br />
<b>Notice</b>:  unserialize(): Error at offset 11 of 36 bytes in <b>[...][...]</b> on line <b>20</b><br />
bool(false)

1 个答案:

答案 0 :(得分:2)

问题是实现Serializable的类和未实现接口的那些使用不同的序列化格式

未实现该接口的类将使用“ O表示法”:

O:1:"A":1:{s:5:"hello";s:5:"world";}

实现Serializable的类将使用“ C表示法”。您的B类,序列化后将如下所示:

C:1:"B":12:{s:5:"world";}

反序列化将不起作用,因为您正试图反序列化为“错误的”定义。

此更改发生在5.6 was reported as a bug and the response was wontfix中,因为旧行为会带来安全隐患。

据我所知,您尝试做的事情仅在PHP 5.3到5.5上有效。以前的文档提到,对于实现Serializable的类,在调用__wakeup()之前先调用unserialize()方法,但这是5.6中删除的一部分。

您需要使用一些解决方法来反序列化该数据,从长远来看,我会将序列化的数据迁移为更安全,更可移植的格式,例如JSON。