|
1.什么是php序列号和反序列化
在开发的过程中常常遇到需要把对象或者数组进行序列号存储,反序列化输出的情况。特别是当需要把数组存储到mysql数据库中时,我们时常需要将数组进行序列化操作。
php序列化(serialize):是将变量转换为可保存或传输的字符串的过程
php反序列化(unserialize):就是在适当的时候把这个字符串再转化成原来的变量使用
这两个过程结合起来,可以轻松地存储和传输数据,使程序更具维护性。
常见的php序列化和反序列化方式主要有:serialize,unserialize;json_encode,json_decode。
2.php类与属性
简单写一段php代码,与Java里面的类、对象类似
运行结果:
3.魔术方法
php中有着魔术方法,以两个__下划线开头的方法称为魔术方法。在触发某个事件后,魔术方法会自动调用。
| 方法名 |
作用 |
| __construct |
构造函数,在创建对象时候初始化对象,一般用于对变量赋初值 |
| __destruct |
析构函数,和构造函数相反,在对象不再被使用时(将所有该对象的引用设为null)或者程序退出时自动调用 |
| __toString |
当一个对象被当作一个字符串被调用,把类当作字符串使用时触发,返回值需要为字符串,例如echo打印出对象就会调用此方法 |
| __wakeup() |
使用unserialize时触发,反序列化恢复对象之前调用该方法 |
| __sleep() |
使用serialize时触发 ,在对象被序列化前自动调用,该函数需要返回以类成员变量名作为元素的数组(该数组里的元素会影响类成员变量是否被序列化。只有出现在该数组元素里的类成员变量才会被序列化) |
| __destruct() |
对象被销毁时触发 |
| __call() |
在对象中调用不可访问的方法时触发,即当调用对象中不存在的方法会自动调用该方法 |
| __callStatic() |
在静态上下文中调用不可访问的方法时触发 |
| __get() |
读取不可访问的属性的值时会被调用(不可访问包括私有属性,或者没有初始化的属性) |
| __set() |
在给不可访问属性赋值时,即在调用私有属性的时候会自动执行 |
| __isset() |
当对不可访问属性调用isset()或empty()时触发 |
| __unset() |
当对不可访问属性调用unset()时触发 |
| __invoke() |
当脚本尝试将对象调用为函数时触发 |
通过触发事件而调用不通的魔术方法
<?php
class animal {
private $name = 'Nolan';
public function sleep(){
echo "<hr>";
echo $this->name . " is sleeping...\n";
}
public function __wakeup(){
echo "<hr>";
echo "调用了__wakeup()方法\n";
}
public function __construct(){
echo "<hr>";
echo "调用了__construct()方法\n";
}
public function __destruct(){
echo "<hr>";
echo "调用了__destruct()方法\n";
}
public function __toString(){
echo "<hr>";
echo "调用了__toString()方法\n";
}
public function __set($key, $value){
echo "<hr>";
echo "调用了__set()方法\n";
}
public function __get($key) {
echo "<hr>";
echo "调用了__get()方法\n";
}
}
$ji = new animal(); //初始化对象,调用__construct
$ji->name = 1; //对不可访问的属性赋值,调用__set
echo $ji->name; //调用不可访问的属性,调用__get
$ji->sleep(); //这里只是为了方便看出调用了sleep,使用serialize序列化之前会自动调用__sleep
$ser_ji = serialize($ji);
print_r($ser_ji);
print_r(unserialize($ser_ji)) //在使用unserialize反序列化时调用__wakeup方法
?>
就会出现如下结果,调用两次__destruct方法是因为在animal类的一个对象被序列号后的字符串又被反序列化时调用
在程序结束时又会调用。
序列化例子
<?php
class object{
public $team = 'Nolan123';
private $team_name = 'power';
protected $team_group = 'biubiu';
function test(){
$this->$team_members = 'hard work!';
}
}
$object = new object();
echo serialize($object);
?>
运行结果
对象类型:对象长度:“对象名称”:类里面的变量个数:{变量类型:长度:“名称”;类型:长度:值;.......}
O是指一个对象,6是object的长度,3是有三个属性,{}里面是属性的内容; ss是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进行反序列化
<?php
class object{
public $team = 'Nolan123';
private $team_name = 'power';
protected $team_group = 'biubiu';
function test(){
echo $this->team." hard work!<br>";
}
}
$object = new object();
$ser = serialize($object);
echo "$ser<br>";
$ser = unserialize($ser);
$ser->test();
var_dump($ser);
?>
调用test方法,用var_dump方法打印所有的对象,可以查看对象内部的数据结构
来源:https://www.cnblogs.com/byErichas/p/14989539.html |