php反序列化之魔术方法超详细讲解
作者:隐形卟 发布时间:2023-11-16 07:24:59
php魔术方法
在php类保留方法中以 “__”两个下划线开头的函数称为魔术方法,我的理解为php类设计中自定义好的函数。
常见的魔术方法有:
__construct(),类的构造函数
__destruct(),类的析构函数
__call(),在对象中调用一个不可访问方法时调用
__callStatic(),用静态方式中调用一个不可访问方法时调用
__get(),获得一个类的成员变量时调用
__set(),设置一个类的成员变量时调用
__isset(),当对不可访问属性调用isset()或empty()时调用
__unset(),当对不可访问属性调用unset()时被调用
__sleep(),执行serialize()时,先会调用这个函数
__wakeup(),执行unserialize()时,先会调用这个函数
__toString(),类被当成字符串时的回应方法
__invoke(),调用函数的方式调用一个对象时的回应方法
__set_state(),调用var_export()导出类时,此静态方法会被调用
__clone(),当对象复制完成时调用
__autoload(),尝试加载未定义的类
__debugInfo(),打印所需调试信息
__construct()与__destruct()
__construct() 构造函数与 __destruct() 析构函数,与其他的语言如java,c#,一样,构造函数就是在对象实例化的时候先执行初始化的方法。
__construct()构造函数只有在new 一个对象的时候会触发,在serialize 序列化和unserialize反序列化中都不会触发
<?php
class demo1{
private $k1;
public function __construct()
{
echo("构造函数被调用"."<br>");
}
public function f1(){
echo("f1 函数被调用");
}
}
echo("0000"."<br>");
$f=new demo1();
echo("1111"."<br>");
$a=serialize($f);
echo("2222"."<br>");
unserialize($a);
?>
输出结果
__destruct() 析构函数则在对象销毁和serialize 反序列化的情况下会被触发。如下
<?php
class demo1{
private $k1;
public function __destruct()
{
echo("析构函数被调用"."<br>");
}
}
$f=new demo1();
echo("0000"."<br>");
$a=serialize($f);
echo("1111"."<br>");
unset($f);
echo("2222"."<br>");
unserialize($a);
?>
输出结果
__call
__call 魔术方法的作用是当前对象调用一个不存在的方法时,就会被触发
<?php
class demo1{
private $k1;
public function f1(){
echo("f1 函数被调用");
}
//当调用不存在的方法时,方法名作为参数传到$name 变量,方法名的输入参数传到arguments参数列表中
public function __call($name, $arguments)
{
// TODO: Implement __call() method.
echo($name."---".$arguments[0]);
}
}
$f=new demo1();
$f->f2("123");//调用不存在的方法f2()
?>
输出结果
__get
__get() 魔术方法是当访问一个对象不存在的变量时就会被触发
<?php
class demo1{
private $k1;
public function f1(){
echo("f1 函数被调用");
}
public function __get($name)//不存在的变量k会以参数传到$name
{
echo($name);
}
}
$f=new demo1();
$f->k;//不存在的变量k
?>
输出结果
__set
__set() 魔术方法是当给一个对象不存在的变量赋值时就会被触发
<?php
header("Content-Type:text/html;charset=utf-8");
highlight_file(__FILE__);
class demo1{
private $k1;
public function f1(){
echo("f1 函数被调用");
}
public function __set($name, $value)
{
echo($name."---".$value);
}
}
$f=new demo1();
$f->k=123; //给不存在的成员变量赋值
?>
输出结果
__isset
当对不可访问属性调用isset()或empty()时会触发,例如访问类的私有属性,类不存在的成员属性
<?php
header("Content-Type:text/html;charset=utf-8");
highlight_file(__FILE__);
class demo1{
private $k1;
public function f1(){
echo("f1 函数被调用");
}
public function __isset($name)
{
echo($name);
}
}
$f=new demo1();
$f2=unserialize(serialize($f));//反序列化
isset($f2->k1);//使用isset方法判断私有成员属性k1
empty($f2->k1);//使用empty方法判断私有成员属性k1
?>
输出结果
__unset
当尝试使用unset() 销毁函数去销毁一个不可访问的成员属性时会触发,不可访问(包括私有成员属性,不存在的成员属性)
<?php
header("Content-Type:text/html;charset=utf-8");
highlight_file(__FILE__);
class demo1{
private $k1;
public function f1(){
echo("f1 函数被调用");
}
public function __unset($name)
{
echo($name);
}
}
$f=new demo1();
$f2=unserialize(serialize($f));//反序列化
unset($f2->k1);//使用unset销毁私有成员属性k1
unset($f2->faaa);//使用unset销毁不存在的成员属性faaa
?>
输出结果
__sleep
当对象被serialize 序列化时触发调用__sleep
<?php
header("Content-Type:text/html;charset=utf-8");
highlight_file(__FILE__);
class demo1{
private $k1;
public function f1(){
echo("f1 函数被调用");
}
public function __sleep()
{
echo("在被序列化时被调用");
}
}
$f=new demo1();
echo("00000"."</br>");
serialize($f);
?>
输出结果
__wakeup
当进行unserialize 反序列化对象时,__wakeup魔术方法会被触发,看起来__wakeup与__sleep 触发条件是相反的
<?php
header("Content-Type:text/html;charset=utf-8");
highlight_file(__FILE__);
class demo1{
private $k1;
public function f1(){
echo("f1 函数被调用");
}
public function __wakeup()
{
echo("在被反序列化时被调用");
}
}
$f=new demo1();
$uz=serialize($f);
echo("00000"."</br>");
unserialize($uz);
?>
输出结果
__toString
如果一个对象类中存在__toString魔术方法,这个对象类被当做字符串进行处理时,就会触发__toString魔术方法,而不会产生错误
<?php
header("Content-Type:text/html;charset=utf-8");
highlight_file(__FILE__);
class demo1{
private $k1;
public function f1(){
echo("f1 函数被调用");
}
public function __toString()
{
echo("__toString 被触发了");
return "";
}
}
$f=new demo1();
echo($f);
?>
输出结果
__invoke
当一个对象类中存在__invoke魔术方法,这个对象类被当作函数进行调用时,就会触发__invoke魔术方法,而不会产生错误
<?php
header("Content-Type:text/html;charset=utf-8");
highlight_file(__FILE__);
class demo1{
private $k1;
public function f1(){
echo("f1 函数被调用");
}
public function __invoke()
{
echo("__invoke 被触发了");
}
}
$f=new demo1();
$f();
?>
输出结果
来源:https://blog.csdn.net/qq_42077227/article/details/127540351
猜你喜欢
- a=1 #1 为对象,def func(x): print('x的地址{}'.form
- 最近有在使用屏幕录制软件录制桌面,在用的过程中突发奇想,使用python能不能做屏幕录制工具,也锻炼下自己的动手能力。接下准备写使用pyth
- 下面看下通过vue提供的keep-alive减少对服务器的请求次数VUE2.0中提供了一个keep-alive方法,可以用来缓存组件,避免多
- 如何使用Office Chart 9.0 制作图表?代码如下:chart90.asp<HTML><HEAD><
- 1. 引言在使用Python的时候,通常会出现如下场景:array = [1, 2, 3, 3, 2, 1, 0, 2]获取array中元素
- 下面先给大家介绍下Python3 执行系统命令并获取实时回显最近在改造一些打包的逻辑,原来在 Windows 下是基于批处理制作的,由于批处
- 一、竞态条件与临界区和同步工具(1)竞态条件一旦数据被多个线程共享,那么就会产生冲突和争用的情况,这种情况被称为竞态条件。这往往会破坏数据的
- 1.算法:设有一组关键字{ K 1 , K 2 ,…, K n };排序开始就认为 K 1 是一个有序序列;让 K 2 插入上述表长为 1
- 在SQL Server数据库的维护或者Web开发中,有时需要在存储过程或者作业等其他数据库操作中调用其它的存储过程,下面介绍其调用的方法一、
- OpenCV中circle与rectangle函数显示,只不过rectangle在图像中画矩形,circle在图像中画圆。void circ
- 前言本文主要给大家介绍了关于Python利用元组代替字典并为元组元素命名的相关内容,下面话不多说了,来一起看看详细的介绍吧场景:一般使用字典
- 这些对文本的操作经常用到, 那我就总结一下。 陆续补充。。。操作:strip_html(cls, text) 去除html标签separat
- mysql时间戳转换select unix_timestamp(); 获取当前时间的时间戳SELECT FROM_UNIXTIME(1529
- 1、使用函数DATE_SUBDATE_SUB函数在当前时间减去一定的时间DATE_SUB(date,INTERVAL expr unit)d
- 忽然想起一个CSS的特性,写一段代码玩玩:<style type="text/css">body {font
- 此文主要讲述的是SQL Server连接中经常出现的3个常见错误,以及对这三个错误的详细分析,如果你其心存好奇的话,以下的文章将会揭开它的神
- 本文为大家分享了pygame游戏之旅的第9篇,供大家参考,具体内容如下在游戏开始之前定义一个函数,用来显示游戏介绍:def game_int
- 这片文章大体概括了一些设计网页中的大问题。希望能给你做下一个网页时给予一些儿启发。1、记住:你能掌控的时间是有限的我仅仅用4秒钟就能浏览完平
- 直接给出例子说明:cs = conn.cursor()img_ids = [1,2,3]sql = "select img_url
- 相信在使用MSSQL数据库下使用事务回滚方式操作多表记录的时候,会经常出现“不能在手动或分布事务方式下创建新的连接”的出错提示信息,这个问题