php反序列化
1.简介
序列化其实就是将数据转化成一种可逆的数据结构,自然,逆向的过程就叫做反序列化。
在网上找到一个比较形象的例子
比如:现在我们都会在淘宝上买桌子,桌子这种很不规则的东西,该怎么从一个城市运输到另一个城市,这时候一般都会把它拆掉成板子,再装到箱子里面,就可以快递寄出去了,这个过程就类似我们的序列化的过程(把数据转化为可以存储或者传输的形式)。当买家收到货后,就需要自己把这些板子组装成桌子的样子,这个过程就像反序列的过程(转化成当初的数据对象)。
php将数据序列化需要两个函数
serialize :将对象格式化有序的字符串
unserilalize:将字符串还原原来的对象
序列化的目的主要是方便数据的传输的存储,php中,序列化和反序列化一般用作缓存,比如:session缓存,cookie等;
常见的序列化格式化
了解即可:
- 二进制 字节数组 json字符串 xml字符串
输出
举个序列化例子
<?php
class object{
public $team = 'joker';
private $team_name = 'hahaha';
protected $team_group = 'biubiu';
function hahaha(){
$this->$team_members = '奥力给';
}
}
$object = new object();
echo serialize($object);
?>
以上是序列化之后的结果,o代表是一个对象,6是对象object的长度,3的意思是有三个类属性,后面花括号里的是类属性的内容,s表示的是类属性team的类型,4表示类属性team的长度,后面的以此类推。值得一提的是,类方法并不会参与到实例化里面。
需要注意的是变量受到不同修饰符(public,private,protected)修饰进行序列化时,序列化后变量的长度和名称会发生变化。
- 使用public修饰进行序列化后,变量$team的长度为4,正常输出。
- 使用private修饰进行序列化后,会在变量$team_name前面加上类的名称,在这里是object,并且长度会比正常大小多2个字节,也就是9+6+2=17。
- 使用protected修饰进行序列化后,会在变量$team_group前面加上*,并且长度会比正常大小多3个字节,也就是10+3=13。
通过对比发现,在受保护的成员前都多了两个字节,受保护的成员在序列化时规则:
\1. 受Private修饰的私有成员,序列化时: \x00 + [私有成员所在类名] + \x00 [变量名]
\2. 受Protected修饰的成员,序列化时:\x00 + * + \x00 + [变量名]
其中,“\x00"代表ASCII为0的值,即空字节,” * " 必不可少。
序列化格式中的字母含义:
a - array b - boolean
d - double i - integer
o - common object r - reference
s - string C - custom object
O - class N - null
R - pointer reference U - unicode string
反序列化
反序列化的话,就依次根据规则进行反向复原。
这边定义一个字符串,然后使用反序列化函数unserialize进行反序列化处理,最后使用var_dump进行输出:
<?php
$ser = 'O:6:"object":3:{s:1:"a";i:1;s:4:"team";s:6:"hahaha";}';
$ser = unserialize($ser);
var_dump($ser);
?>
O:4:"test":2:{s:1:"a";s:9:"xiaoshizi";s:1:"b";s:8:"laoshizi";}
输出(O代表Object是对象的意思,也是类;s)
a:3:{i:0;s:4:“xiao”;i:1;s:3:“shi”;i:2;s:2:“zi”;}
a:array代表是数组,后面的3说明有三个属性 i:代表是整型数据int,后面的0是数组下标
s:代表是字符串,后面的4是因为xiao长度为4
依次类推
2.反序列化的常见的魔术方法
为php常见的魔术方法:
方法名 | 作用 |
---|---|
__construct | 构造函数,在创建对象时候初始化对象,一般用于对变量赋初值 |
__destruct | 析构函数,和构造函数相反,在对象不再被使用时(将所有该对象的引用设为null)或者程序退出时自动调用 |
__toString | 当一个对象被当作一个字符串被调用,把类当作字符串使用时触发,返回值需要为字符串,例如echo打印出对象就会调用此方法 |
__wakeup() | 使用unserialize时触发,反序列化恢复对象之前调用该方法 |
__sleep() | 使用serialize时触发 ,在对象被序列化前自动调用,该函数需要返回以类成员变量名作为元素的数组(该数组里的元素会影响类成员变量是否被序列化。只有出现在该数组元素里的类成员变量才会被序列化) |
__destruct() | 对象被销毁时触发 |
__call() | 在对象中调用不可访问的方法时触发,即当调用对象中不存在的方法会自动调用该方法 |
__callStatic() | 在静态上下文中调用不可访问的方法时触发 |
__get() | 读取不可访问的属性的值时会被调用(不可访问包括私有属性,或者没有初始化的属性) |
__set() | 在给不可访问属性赋值时,即在调用私有属性的时候会自动执行 |
__isset() | 当对不可访问属性调用isset()或empty()时触发 |
__unset() | 当对不可访问属性调用unset()时触发 |
__invoke() | 当脚本尝试将对象调用为函数时触发 |
额外提一下__tostring的具体触发场景:
(1)
echo($obj) / print($obj)
打印时会触发(2) 反序列化对象与字符串连接时
(3) 反序列化对象参与格式化字符串时
(4) 反序列化对象与字符串进行比较时(PHP进行比较的时候会转换参数类型)
(5) 反序列化对象参与格式化SQL语句,绑定参数时
(6) 反序列化对象在经过php字符串函数,如 strlen()、addslashes()时
(7) 在in_array()方法中,第一个参数是反序列化对象,第二个参数的数组中有toString返回的字符串的时候toString会被调用
(8) 反序列化的对象作为 class_exists() 的参数的时候