Serializable[自定义序列化的接口] :
实现此接口的类将不再支持 __sleep() 和 __wakeup()。
作用:
为一些高级的序列化场景提供支持。__sleep()和__wakeup()有一些问题,这些问题再SPL中都得到解决。【书上说的,具体的问题之看到了“总结”中的第一个】
总结:(根据看到的例子总结,绝对地不全)
1.魔术方法不能序列化基类的私有变量,SPL可以。
2.SPL可通过子类serialized父类。
3.SPL可以serialize全部的子类变量,子类不需要重写serialize方法。
以例服人:
1.魔术方法不能序列化基类私有变量
<?php error_reporting( E_ALL ); //开启全部错误提示 class Base { private $base; public function __construct() { $this->base = "base"; } } class Sub extends Base{ private $sub; public function __construct() { parent::__construct(); //调用父类的构造方法,为父类中的base赋值 $this->sub = "sub"; } public function __sleep() { return array( "sub", "base" ); } } $instance = new Sub(); $serialized = serialize( $instance ); echo $serialized."\n"; $restored = unserialize( $serialized ); //执行输出 //Notice: serialize(): "base" returned as member variable from __sleep() but does not exist //O:3:"Sub":2:{s:8:"NULSubNULsub";s:3:"sub";s:4:"base";N;}
使用SPL的Serializable接口就可以解决这个问题
<?php error_reporting( E_ALL ); //开启全部错误提示 class Base implements Serializable { private $base; public function __construct() { $this->base = "base"; } public function serialize() { return serialize( $this->base ); } public function unserialize( $serialized ) { $this->base = unserialize( $serialized ); } public function getBase() { return $this->base; } } class Sub extends Base{ private $sub; public function __construct() { parent::__construct(); //调用父类的__construct,为父类的base赋值,可通过调用父类的getBase方法获取改值。 $this->sub = "sub"; } public function serialize() { $baseSerialized = parent::serialize(); //注意这个地方 return serialize( array( $this->sub, $baseSerialized ) ); } public function unserialize( $serialized ) { $temp = unserialize( $serialized ); $this->sub = $temp[0]; parent::unserialize( $temp[1] ); } } $instance = new Sub(); $serialized = serialize( $instance ); echo $serialized."\n"; $restored = unserialize( $serialized ); echo $restored->getBase(); //执行输出 //C:3:"Sub":43:{a:2:{i:0;s:3:"sub";i:1;s:11:"s:4:"base";";}} //base
2.通过子类序列化父类
<?php class Base implements Serializable{ private $data; public function __construct( $data ) { $this->data = $data; } public function getData() { return $this->data; } public function serialize() { return serialize( $this->data ); } public function unserialize( $serialize ) { $this->data = unserialize( $serialize ); } } class Sub extends Base{ private $id; private $name; public function __construct( $id, $name, $data ) { parent::__construct( $data ); $this->id = $id; $this->name = $name; } public function serialize() { return serialize( array( "id" => $this->id, "name" => $this->name, "parentData" => parent::serialize() //注意这里 ) ); } public function unserialize( $serialize ) { $temp = unserialize( $serialize ); $this->id = $temp["id"]; $this->name = $temp["name"]; parent::unserialize( $temp["parentData"] ); } public function getVar() { return $this->id."|".$this->name."|".parent::getData(); } } $instance = new Sub( 12, "lee", "hello world" ); $serialized = serialize( $instance ); echo $serialized."\n"; $unserialized = unserialize( $serialized ); echo $unserialized->getVar(); //echo //C:3:"Sub":86:{a:3:{s:2:"id";i:12;s:4:"name";s:3:"lee";s:10:"parentData";s:19:"s:11:"hello world";";}} //12|lee|hello world
3.子类不用重写父类serialize方法也能序列化自身的变量,用get_object_vars()函数配合。
<?php class Pot implements Serializable { protected $_a; protected $_b; public function serialize() { return serialize( get_object_vars( $this ) ); } public function unserialize( $data ) { $values = unserialize( $data ); foreach ( $values as $key=>$value ) { $this->$key = $value; } } } //And now one descendant: class PotId extends Pot { protected $_k; } class Pots extends PotId { protected $_l; } $pots = new Pots(); echo serialize( $pots ); //echo //C:4:"Pots":50:{a:4:{s:2:"_l";N;s:2:"_k";N;s:2:"_a";N;s:2:"_b";N;}}
时间: 2024-08-13 08:42:42