文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

php反序列化之魔术方法超详细讲解

2022-11-13 19:14

关注

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();
?>

输出结果

到此这篇关于php反序列化之魔术方法超详细讲解的文章就介绍到这了,更多相关php反序列化 内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     801人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     348人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     311人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     432人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     220人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯