PHP序列化(serialize)
· 数据类型的序列化
<?php
class CC {
public $data;
private $pass;
public function __construct($data, $pass)
{
$this->data = $data;
$this->pass = $pass;
}
}
class DD extends CC
{
public function __construct($data,$pass)
{
parent::__construct($data,$pass);
}
}
trait AA
{
public $a;
public function __construct()
{
$this->a=2;
}
public function say()
{
echo 'hello';
}
}
trait BB
{
public function test()
{
echo 'world';
}
}
class FF
{
use AA,BB;
}
$number = 34;
$str = 'uusama';
$bool = true;
$null = NULL;
$arr = array('a' => 1, 'b' => 2);
$cc = new CC('uu', true);
$dd = new DD('uu', true);
$ff =new FF();
var_dump(serialize($number));
var_dump(serialize($str));
var_dump(serialize($bool));
var_dump(serialize($null));
var_dump(serialize($arr));
var_dump(serialize($cc));
var_dump(serialize($dd));
var_dump(serialize($ff));
输出结果为:
- int 类型 :i:34;
- string 类型 :s:6:"uusama";
- bool 类型 :b:1;
- null 类型 :N;
- array 类型 :a:2:{s:1:"a";i:1;s:1:"b";i:2;}
- 普通对象 :O:2:"CC":2:{s:4:"data";s:2:"uu";s:8:"\000CC\000pass";b:1;}
- 单继承对象 :O:2:"DD":2:{s:4:"data";s:2:"uu";s:8:"\000CC\000pass";b:1;}
- 多继承对象:O:2:"FF":1:{s:1:"a";i:2;}
__sleep()与__wakeup()
如果单纯的序列化对象,再反序列化。那么他只是实现了json_encode的功能,重复造轮子意义不大。序列化更强调的是状态的冻结、与状态的恢复。
<?php
class CC {
private $content;
private $test;
public function __construct($content,$test=0)
{
$this->content = $content;
$this->test=$test;
}
public function __sleep()
{
return [$this->content];
}
}
$dd = new CC('uu');
var_dump(serialize($dd));
带__sleep()的情况序列化结果:
O:2:"CC":1:{s:2:"uu";N;}
注释__sleep()的结果:
O:2:"CC":2:{s:11:"\000CC\000content";s:2:"uu";s:8:"\000CC\000test";i:0;}
总结一下 sleep
如果sleep 有明确的返回数组 ,则系统按照sleep 函数的内容保存对应的数值和类型 。如果没有sleep函数,系统会默认保存所有的参数值及类型;
ps: 序列化不能实现函数和闭包序列化后再反序列化调用的操作;
__wakeup()
<?php
class CC {
private $content;
private $test;
public function __construct($content,$test=0)
{
$this->content = $content;
$this->test=$test;
}
public function __wakeup()
{
echo $this->test.PHP_EOL;
}
}
$dd = new CC('uu');
var_dump($dd=serialize($dd));
var_dump(unserialize($dd));
结果如下:
class CC#1 (2) {
private $content =>
string(2) "uu"
private $test =>
int(0)
}
总结
__wakeup函数可以在反序列化的时候执行自己的逻辑。如果该函数不存在,反序列化只会对应对象的实例。
PHP json_encode编码
<?php
class CC {
public $data;
private $pass;
public function __construct($data, $pass)
{
$this->data = $data;
$this->pass = $pass;
}
}
class DD extends CC
{
public function __construct($data,$pass)
{
parent::__construct($data,$pass);
}
}
trait AA
{
public $a;
public function __construct()
{
$this->a=2;
}
public function say()
{
echo 'hello';
}
}
trait BB
{
public function test()
{
echo 'world';
}
}
class FF
{
use AA,BB;
}
$number = 34;
$str = 'uusama';
$bool = true;
$null = NULL;
$arr = array('a' => 1, 'b' => 2);
$cc = new CC('uu', true);
$dd = new DD('uu', true);
$ff =new FF();
var_dump(json_encode($number));
var_dump(json_encode($str));
var_dump(json_encode($bool));
var_dump(json_encode($null));
var_dump(json_encode($arr));
var_dump(json_encode($cc));
var_dump(json_encode($dd));
var_dump(json_encode($ff));
我们同样对一个基础的类实行json_encode ,结果如下
- int 类型 :34;
- string 类型 :"uusama";
- bool 类型 :"true"
- null 类型 :"null"
- array 类型 :{"a":1,"b":2}
- 普通对象 :{"data":"uu"}
- 单继承对象 :{"data":"uu"}
- 多继承对象:{"a":2}
现在我们在使用json_decode 来解码
- int 类型 :int(34)
- string 类型 :string(6) "uusama"
- bool 类型 :bool(true)
- null 类型 :NULL
- array 类型 :class stdClass#4 (2) {
public $a =>
int(1)
public $b =>
int(2)
} - 普通对象 :class stdClass#4 (1) {
public $data =>
string(2) "uu"
} - 单继承对象 :class stdClass#4 (1) {
public $data =>
string(2) "uu"
} - 多继承对象:class stdClass#4 (1) {
public $a =>
int(2)
}
总结一下 json_encode()
json编码之后也能恢复原有的数据,也可以恢复部分数据的类型,区别在于恢复对象的时候,json_encode编码只会保存类的属性参数,不能保存类的完整信息,例如类的名称、类的私有变量、受保护的变量。
本章总结
json_encode 和类的序列化 相同点在于 保存数据的时候 包含 int、string、bool、array 时 具有相同的作用,可编译也可反编译恢复数据的值和类型、不同点在于,序列化除了能够保存数据之外 ,还能清晰的保存对象的信息,变量的可访问类别,和一系列的操作,而json_encode 只可以保存类的公共变量值和类型。所以 我们在选择保存对象的时候,可以根据对象的种类 选择合理的保存方式、另外在提一个注意点,json_encode的编码效率要高于序列化、怎么取舍看各位使用情况了。