php序列化和反序列化

一,什么是序列化和反序列化

序列化

序列化是将对象转化为可存储或传输的字符串格式的过程。在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()都可以准确的打印出属性的访问修饰符。 

 

  • 27
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
PHP序列化是将PHP对象转换为字符串的过程,以便在存储或传输时使用。序列化后的字符串可以通过反序列化操作重新还原为原始的PHP对象。\[1\] 在PHP中,可以使用serialize()函数将对象序列化为字符串,然后使用unserialize()函数将字符串反序列化为对象。这样可以方便地在不同的环境中传递和存储对象数据。 然而,反序列化操作也存在安全风险。恶意用户可以构造特定的序列化字符串,以触发PHP反序列化漏洞,导致代码执行或敏感信息泄露。因此,在进行反序列化操作时,需要谨慎处理输入数据,验证和过滤不可信的序列化字符串。 除了使用serialize()和unserialize()函数,还可以利用一些特殊的方式来触发PHP反序列化漏洞。例如,通过Phar反序列化,可以在不使用unserialize()函数的情况下触发PHP反序列化漏洞。当使用phar://伪协议读取phar文件时,会自动反序列化meta-data中存储的信息,从而导致漏洞触发。\[2\]\[3\] 因此,在开发和使用PHP应用程序时,需要注意对序列化反序列化操作进行安全处理,避免潜在的安全风险。这包括对输入数据进行验证和过滤,限制反序列化操作的权限,以及及时更新和修复可能存在的漏洞。 #### 引用[.reference_title] - *1* *2* *3* [PHP序列化反序列化](https://blog.csdn.net/weixin_44033675/article/details/116809651)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值