6.自定义对象序列化
6.1.PHP 4 中自定义对象序列化
PHP 4 中提供了 __sleep 和 __wakeup 这两个方法来自定义对象的序列化。不过这两个函数并不改变对象序列化的格式,影响的仅仅是被序列化字段的个数。关于它们的介绍,在 PHP 手册中写的还算比较详细。这里就不再多做介绍了。
6.2.PHP 5 中自定义对象序列化
PHP 5 中增加了接口(interface)功能。PHP 5 本身提供了一个 Serializable 接口,如果用户在自己定义的类中实现了这个接口,那么在该类的对象序列化时,就会被按照用户实现的方式去进行序列化,并且序列化后的标示不再是 O,而改为 C。C 标示的格式如下:
C:<name length>:"<class name>":<data length>:{<data>} |
其中 <name length> 表示类名 <class name> 的长度,<data length> 表示自定义序列化数据 <data> 的长度,而自定义的序列化数据 <data> 是完全的用户自己定义的格式,与 PHP 序列化格式可以完全无关,这部分数据由用户自己实现的序列化和反序列化接口方法来管理。
Serializable 接口中定义了 2 个方法,serialize() 和 unserialize($data),这两个方法不会被直接调用,而是在调用 PHP 序列化函数时,被自动调用。其中 serialize 函数没有参数,它的返回值就是 <data> 的内容。而 unserialize($data) 有一个参数 $data,这个参数的值就是 <data> 的内容。这样大家应该就明白了,实际上接口中 serialize 方法就是让用户来自己序列化对象中的内容,序列化后的内容格式,PHP 并不关心,PHP 只负责把它充填到 <data> 中,等到反序列化时,PHP 只负责取出这部分内容,然后传给用户实现的 unserialize($data) 接口方法,让用户自己去反序列化这部分内容。
下面举个简单的例子,来说明 Serializable 接口的使用:
class MyClass implements Serializable { public $member; function MyClass() { $this->member = 'member value'; } public function serialize() { return wddx_serialize_value($this->member); } public function unserialize($data) { $this->member = wddx_deserialize($data); } } $a = new MyClass(); echo serialize($a); echo "\n"; print_r(unserialize(serialize($a))); |
输出结果为(浏览器中的源代码):
C:7:"MyClass":90:{<wddxPacket version='1.0'><header/><data><string>member value</string></data></wddxPacket>} MyClass Object ( [member] => member value ) |
因此如果想用其它语言来实现 PHP 序列化中的 C 标示的话,也需要提供一种这样的机制,让用户自定义类时,能够自己在反序列化时处理 <data> 内容,否则,这些内容就无法被反序列化了。