一,什么是序列化和反序列化
序列化
序列化是将对象转化为可存储或传输的字符串格式的过程。在php中,可以使用serialize()函数将对象,数组或其它数据类型序列化称为一个字符串,以便将其保存到文件或者进行网络传输。
反序列化
反序列化是将之前序列化得到的字符串重新转换为原始的php数据结构或对象的过程。在php中,可以使用unserialize()函数对序列化后的字符串进行反序列化操作。
二,为什么要序列化和反序列化
在php中,序列化和反序列化是用来实现数据持久化,数据传输和数据存储的重要概念。
既然是面向对象的操作,那我们先了解什么是面向对象和面向过程。
举个例子
过年了,家里要打扫卫生。
你先扫地,再擦桌子,再拖地。一件一件的完成。这就是面向过程。
你扫地,爸爸擦桌子,妈妈拖地。一起完成,各干各的。这就是面向对象。
关键区别在于,面向过程的实现方式更加关注解决问题的步骤和过程。
而面向对象的实现更加关注对象的行为和状态。
三,什么是类和对象
什么是类?
类是面向对象编程中的一个关键概念,它是对具有相似特征和行为的对象的抽象描述,类定义了对象可以拥有的属性(成员变量)和行为(方法)。
什么是对象?
对象是类的实例化产物,是类的具体实体。
直接看代码
<?php
class car { //定义一个car类
public $brand; //public是访问修饰符
public $type;
public $color;
//定义方法
public function move(){
echo "汽车启动!";
}
public function speed_up(){
echo "汽车加速!";
}
public function stop(){
echo "汽车停止!";
}
}
//实例化对象
$a=new car();
//设置属性值
$a->brand="奥迪";
$a->type="rs7";
$a->color="black";
//调用方法
$a->move();
$a->speed_up();
$a->stop();
echo $a->brand;
?>
运行结果
这里的类就是car,对象就是$a。
类的继承
子类和父类,说白了就是爸爸和儿子的关系,子类可以继承父类的属性和方法。
代码展示
<?php
class car {
public $brand;
public $type;
public $color;
//方法
public function move(){
echo "汽车启动!";
}
public function speed_up(){
echo "汽车加速! ";
}
public function stop(){
echo "汽车停止! ";
}
}
class ect extends car{
public $电池容量;
public function 充电(){
echo "充电中---";
}
}
$b=new ect();
$b->电池容量='120kmh';
$b->brand='雅迪';
echo "<br>";
$b->speed_up();
$b->充电();
echo $b->brand;
?>
从上图可以看出,我定义了一个名为ect的子类,而定义子类需要extends关键字。
在子类中,我只定义了一个属性和一个方法,但是我在调用时,却可以直接调用父类的属性和方法。这儿就是类的继承。
运行结果
除了类的继承,访问修饰符也同样重要。
四,访问修饰符
一共有三个访问修饰符,public,protected,private
在php类中不写访问修饰符默认的访问权限为public
调用属性和方法也有三种情况,分别是类中,类外,子类。
由图可以看到,public无论在哪里都可以访问,protected只有在类中和子类中可以访问,private只可以在类中调用。
<?php
class people{
public $name='学生';
protected $sex='girl';
private $age='18';
function speak(){
echo '在类自身调用:'.$this->name;
echo '在类自身调用:'.$this->sex;
echo '在类自身调用'.$this->age;
//在方法指定属性需要$this
}
}
$a=new people();
echo '在类外调用'.$a->name;
echo '在类外调用'.$a->sex;
echo '在类外调用'.$a->age;
$a->speak();
?>
运行结果
可以看到只输出了学生,因为学生的属性名name的修饰符为public,在哪里都可以访问,而sex和age就不行了,都不能在类外调用。
<?php
class people{
public $name='学生';
protected $sex='girl';
private $age='18';
function speak(){
echo '在类自身调用:'.$this->name;
echo "<br/>";
echo '在类自身调用:'.$this->sex;
echo "<br/>";
echo '在类自身调用'.$this->age;
echo "<br/>";
//在方法指定属性需要$this
}
}
$a=new people();
//echo '在类外调用'.$a->name;
//echo "<br/>";
// echo '在类外调用'.$a->sex;
// echo '在类外调用'.$a->age;
//虽然不能直接调用属性,但是可以调用方法,方法中的属性也属于类中调用
$a->speak();
?>
当我不在类外调用类的属性时,直接在类外调用方法。
发现成功输出,虽然sex和age不能再类外调用,但是我直接在类外调用方法,方法调用了三个属性,相当于还是在类中,因为方法在类中。
<?php
class people{
public $name='学生';
protected $sex='girl';
private $age='18';
function speak(){
echo '在类自身调用:'.$this->name;
echo "<br/>";
echo '在类自身调用:'.$this->sex;
echo "<br/>";
echo '在类自身调用'.$this->age;
echo "<br/>";
//在方法指定属性需要$this
}
}
class student extends people{
function speak1()
{
echo '在子类调用:'.$this->name;
echo "<br/>";
echo '在子类调用:'.$this->sex;
echo "<br/>";
echo '在子类调用:'.$this->age;
}
}
//public,protected修饰符在子类中都能调用
$c=new student();
$c->speak1();
?>
运行结果
创建一个子类student,输出结果发现 age属性没有被调用,以为它的修饰符时private,只能在类中被调用,不能再子类和类外调用。
说完修饰符,我们就就该正式进入序列化和反序列化的篇章了。
五,演示
序列化
<?php
class people{
private $age=18;
public $name='kobe';
protected $height='198cm';
public function speak(){
echo 'hello';
}
}
$a=new people();
$b=serialize($a);//将对象序列化成字符串
echo $b;
?>
用serialize()函数将对象序列化成字符串。
// O表示对象类型
// 6表示类名的长度
// "people"表示类名
// 3表示类中有三个属性
// s表示字符型
// 11表示属性名的长度,因为age是私有属性,所以它的属性名的长度组成是一个空格+类名+一个空格+属性名
// peopleage这里表示私有属性的属性名,在people前后有两个空格
// i表示数字型
// 18表示私有属性age的值
// name是public修饰符,看到什么就是什么
// 9表示protected修饰符的长度,长度组成一个空格+*+一个空格+属性名
//对象的方法不会在序列化显示,但是它是有的
总结,不同修饰符,序列化后的属性名长度不同。
public 不变
protected 一个空格+*+一个空格+属性名
private 一个空格+类名+一个空格+属性名
反序列化
<?php
class people{
private $age=18;
public $name='kobe';
protected $height='198cm';
public function speak(){
echo 'hello';
}
}
$a=new people();
$b=serialize($a);
print_r(unserialize($b));
echo "<br/>";
var_dump(unserialize($b));
?>
反序列化的结果不能用echo函数,只能用print_r(),var_dump()。
第一行时print_r()打印的结果,第二行是var_dump()打印的结果,这里的#2没有实际意义,只是php里面的标识符。不管是print_r(),还是var_dump()都可以准确的打印出属性的访问修饰符。