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;

SPL--Serializable的更多相关文章

  1. PHP SPL(PHP 标准库)

    一.什么是SPL? SPL是用于解决典型问题(standard problems)的一组接口与类的集合.(出自:http://php.net/manual/zh/intro.spl.php) SPL, ...

  2. PHP标准库 (SPL) 笔记

    简介 SPL是Standard PHP Library(PHP标准库)的缩写. The Standard PHP Library (SPL) is a collection of interfaces ...

  3. SPL 全面剖析

    SPL 全面剖析 来自百度百科 http://baike.baidu.com/view/1130234.htm?fr=aladdin SPL(Standard PHP Library) IN PHP5 ...

  4. SPL接口学习总结

    迭代器接口描述(接口在C里定义,这只是描述) interface Iterator { public function current(); public function key(); public ...

  5. 【SPL标准库专题(9)】 Datastructures:SplObjectStorage

    PHP SPL SplObjectStorage是用来存储一组对象的,特别是当你需要唯一标识对象的时候. PHP SPL SplObjectStorage类实现了Countable,Iterator, ...

  6. 【SPL标准库专题(3)】 Classes

    我把SPL分为四个部分:Iterator,Classes,Datastructures,Function:而其中classes是就是做一些类的介绍(Iterator与Datastructures相关的 ...

  7. 【SPL标准库专题(2)】 Iterator

    Iterator界面 本段内容来自阮一峰老师再加自己的部分注解 SPL规定,所有部署了Iterator界面的class,都可以用在foreach Loop中.Iterator界面中包含5个必须部署的方 ...

  8. 深入浅出 PHP SPL(PHP 标准库)(转)

    一.什么是spl库? SPL是用于解决典型问题(standard problems)的一组接口与类的集合. 此扩展只能在php 5.0以后使用,从PHP 5.3.0 不再被关闭,会一直有效.成为php ...

  9. SPL数据结构

    数据结构是计算机存储.组织数据的方式. SPL提供了双向链表.堆栈.队列.堆.降序堆.升序堆.优先级队列.定长数组.对象容器. 基本概念Bottom:节点,第一个节点称Bottom:Top:最后添加的 ...

  10. PHP SPL标准库-数据结构

    SPL是用于解决典型问题的一组接口与类的集合. 双向链表 SplDoublyLinkedList SplStack SplQueue 双链表是一种重要的线性存储结构,对于双链表中的每个节点,不仅仅存储 ...

随机推荐

  1. 【BZOJ 3672】【UOJ #7】【NOI 2014】购票

    http://www.lydsy.com/JudgeOnline/problem.php?id=3672 http://uoj.ac/problem/7 链上的情况可以用斜率优化dp.树上用斜率优化d ...

  2. java-a实现压缩与解压缩(zip、gzip)

    zip扮演着归档和压缩两个角色:gzip并不将文件归档,仅只是对单个文件进行压缩,所以,在UNIX平台上,命令tar通常用来创建一个档案文件,然后命令gzip来将档案文件压缩. Java I/O类库还 ...

  3. 【HDU 5810多校】Balls and Boxes(打表/数学)

    1.打表找规律,下面是打表程序: #include <iostream> #include <cstdio> #define ll long long #define N 10 ...

  4. subroutines of perl

    #!/usr/bin/perl -w @students = qw/Doreen Oskar Elin Sangeet Malin/; &next_student; &next_stu ...

  5. wamp服务下部署禅道或其它项目时访问缓慢的解决办法

    原因其实很简单: WAMP服务默认是不支持外网访问的,如果公司内外网在一起就会引起缓慢甚至超时的问题,直接修改WAPM的配置文件让它可以访问外网即可解决问题.   解决的方法/步骤   1.解决办法: ...

  6. 细说new与malloc的10点区别

    前言 几个星期前去面试C++研发的实习岗位,面试官问了个问题: new与malloc有什么区别? 这是个老生常谈的问题.当时我回答new从自由存储区上分配内存,malloc从堆上分配内存:new/de ...

  7. 精通Web Analytics 2.0 (1) 引言

    精通Web Analytics 2.0 : 用户中心科学与在线统计艺术 前言 我对这本书抱有一个简单的愿望,也许是崇高的目标:改变世界对线上事情作决策的方式. 长久以来,我们在线上的举动已经被准确的归 ...

  8. [bzoj3694]最短路

    Description 给出一个$n$个点$m$条边的无向图,$n$个点的编号从$1-n$,定义源点为$1$. 定义最短路树如下:从源点$1$经过边集$T$到任意一点$i$有且仅有一条路径,且这条路径 ...

  9. js-自制轮播插件!

    刚接触轮播的时候,感觉这种东西好高端,后来学习了jquery后,发现原来挺简单的,而且实现轮播也有很多形式,我用jquery自制了一个轮播插件,其实我这个说是插件,好像其实就是一个高度抽象的函数而已. ...

  10. 【译】用boosting构建简单的目标分类器

    用boosting构建简单的目标分类器 原文 boosting提供了一个简单的框架,用来构建鲁棒性的目标检测算法.这里提供了必要的函数来实现它:100% MATLAB实现,作为教学工具希望让它简单易得 ...