SPL--Serializable
Serializable[自定义序列化的接口] :
实现此接口的类将不再支持 __sleep() 和 __wakeup()。
作用:
为一些高级的序列化场景提供支持。__sleep()和__wakeup()有一些问题,这些问题再SPL中都得到解决。【书上说的,具体的问题之看到了“总结”中的第一个】
总结:(根据看到的例子总结,绝对地不全)
1.魔术方法不能序列化基类的私有变量,SPL可以。
2.SPL可通过子类serialized父类。
3.SPL可以serialize全部的子类变量,子类不需要重写serialize方法。
4.在serialize方法中return NULL 来防止序列化。
以例服人:
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;}}
4.为了防止通过unserialize得到对象,可以在serialize方法中return NULL,这将放回一种序列化后的NULL。
<?php class testNull implements Serializable{ public function serialize() { return NULL; } public function unserialize($serialized) { } } $instance = new testNull(); $serialized = serialize($instance); echo $serialized; //N;