我有一个使用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)
答案 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。