序列化
在PHP中,序列化用于存储或传递 PHP 的值的过程中,同时不丢失其类型和结构。
序列化函数:
string serialize ( mixed $value )
说明:
返回对象的字符串表示。
返回值:
返回对象的字符串表示或者 NULL 。
参数:
任意类型。
对象的序列化
注意:序列化担当着对象析构器的角色。在此方法之后,__destruct() 方法将不会被调用。
<?php
class aa{
public $a;
public $b;
public function __construct()
{
# 构造函数
$this->a='hello';
$this->b='world';
}
}
$obj = new aa;
$str=serialize($obj);
var_dump($str);
?>
输出结果:
string(53) "O:2:"aa":2:{s:1:"a";s:5:"hello";s:1:"b";s:5:"world";}"
解释:
string(53):指序列化后的字符类型为字符串长度为53。
O:strlen(object name):object name:object size:{s:strlen(property name):property name:property definition;(repeated per property)}
数组的序列化
<?php
$a=array('aaaa',100,2.5,true);
$str=serialize($a);
var_dump($str);
?>
输出结果:
string(49) "a:4:{i:0;s:4:"aaaa";i:1;i:100;i:2;d:2.5;i:3;b:1;}"
解释:
a:size:{key 类型:key长度:key的值;value类型:value长度:value的值;(repeated per element)}
默认int,double,bool不显示长度
字符串的反序列化
<?php
$a='asdf';
$str=serialize($a);
var_dump($str);
?>
输出结果:
string(11) "s:4:"asdf";"
解释:
s:size:value;
数字的序列化
<?php
$a=6;
$b=6.6;
$str1=serialize($a);
$str2=serialize($b);
var_dump($str1);
echo "<br>";
var_dump($str2);
?>
输出结果:
string(4) "i:6;"
string(21) "d:6.5999999999999996;"
解释:
i:value;
d:value;
这里至于为什么是6.5999999999999996,我也不知道。
布尔和NULL的序列化
<?php
$a=false;
$b=NULL;
$str1=serialize($a);
$str2=serialize($b);
var_dump($str1);
echo "<br>";
var_dump($str2);
?>
输出结果:
string(4) "b:0;"
string(2) "N;"
解释:
b:value;(保存1或0)
N;
反序列化
反序列化函数:
mixed unserialize ( string $str )
unserialize()反序列化函数用于将单一的已序列化的变量转换回序列化之前的值。
参数:
对象的字符串表示。
返回值:
返回没有序列化之前的原始值。
对象的反序列化
<?php
class aa{
public $a;
public $b;
public function __construct()
{
# 构造函数
$this->a='hello';
$this->b='world';
}
public function __toString(){
#对象以字符串形式输出时自动调用
echo '调用了__toString()函数';
return $this->a;
}
}
// $obj = new aa;
// $str=serialize($obj);
// var_dump($str);
$str='O:2:"aa":2:{s:1:"a";s:5:"hello";s:1:"b";s:5:"world";}';
$obj=unserialize($str);
var_dump($obj);
echo "<br>";
echo $obj;
?>
输出结果:
object(aa)#2 (2) { ["a"]=> string(5) "hello" ["b"]=> string(5) "world" }
调用了__toString()函数hello
解释:
object(aa):指反序列化后的值为对象,类名为aa。
注意:这里生成了一个对象但没有调用构造函数。
这里我们可以改变里面的变量值:
<?php
class aa{
public $a;
public $b;
public function __construct()
{
# 构造函数
$this->a='hello';
$this->b='world';
}
public function __toString(){
echo '调用了__toString()函数';
return $this->a;
}
}
// $obj = new aa;
// $str=serialize($obj);
// var_dump($str);
$str='O:2:"aa":2:{s:1:"a";s:3:"asd";s:1:"b";s:5:"world";}';
$obj=unserialize($str);
var_dump($obj);
echo "<br>";
echo $obj;
?>
输出结果:
object(aa)#2 (2) { ["a"]=> string(3) "asd" ["b"]=> string(5) "world" }
调用了__toString()函数asd
说明我们已经改变啦变量a的值。所以这里存在漏洞。
数组的反序列化
<?php
// $a=array('a'=>'aaaa',100,2.5,true);
// $str=serialize($a);
// var_dump($str);
$b='a:4:{s:1:"a";s:4:"aaaa";i:0;i:100;i:1;d:2.5;i:2;b:1;}';
$arr=unserialize($b);
echo "<pre>";
print_r($arr);
echo "</pre>";
?>
输出结果:
Array
(
[a] => aaaa
[0] => 100
[1] => 2.5
[2] => 1
)
解释:
如果bool类型的值在转化回数组的过程中1转换为1,0转换为空。
字符串反序列化
<?php
// $a='asdf';
// $str=serialize($a);
// var_dump($str);
$b='s:4:"asdf";';
$str=unserialize($b);
echo $str;
?>
输出结果:
asdf
数字的反序列化
<?php
// $a=6;
// $b=6.6;
// $str1=serialize($a);
// $str2=serialize($b);
// var_dump($str1);
// echo "<br>";
// var_dump($str2);
$a='i:6;';
$b='d:6.5999999999999996;';
$str1=unserialize($a);
$str2=unserialize($b);
var_dump($str1);
echo "<br>";
var_dump($str2);
?>
输出结果:
int(6)
float(6.6)
发现:小数点后有14位时开始对十分位四舍五入。
布尔值和NULL的反序列化
<?php
// $a=false;
// $b=NULL;
// $str1=serialize($a);
// $str2=serialize($b);
// var_dump($str1);
// echo "<br>";
// var_dump($str2);
$a='b:0;';
$b='N;';
$str1=unserialize($a);
$str2=unserialize($b);
var_dump($str1);
echo "<br>";
var_dump($str2);
?>
输出结果:
bool(false)
NULL
总结
序列化和反序列化是个很神奇的东西。需要多多了解和掌握。
如有不足请指出。