一篇文章带你入门PHP魔术方法

news2024/11/26 2:50:23

PHP魔术方法

PHP 中的"魔术方法"是一组特殊的方法,它们在特定情况下自动被调用。这些方法的名称都是以两个下划线(__)开头。魔术方法提供了一种方式来执行各种高级编程技巧,使得对象的行为可以更加灵活和强大。以下是一些常见的PHP魔术方法:

  1. __construct(): 构造函数,当一个新对象被创建时调用。
  2. __destruct(): 析构函数,当一个对象不再被使用时调用。
  3. __call($name, $arguments): 当调用一个对象中不存在的方法时调用。
  4. __callStatic($name, $arguments): 当调用一个静态方法不存在时调用。
  5. __get($name): 当读取一个不可访问的属性时调用。
  6. __set($name, $value): 当设置一个不可访问的属性时调用。
  7. __isset($name): 当对不可访问的属性调用 isset()empty() 时调用。
  8. __unset($name): 当对不可访问的属性调用 unset() 时调用。
  9. __sleep(): 在序列化对象之前调用,通常用于清理任务或返回数组中的哪些属性需要被序列化。
  10. __wakeup(): 在反序列化对象时调用,通常用于重新建立数据库连接或执行其他初始化操作。
  11. __toString(): 当对象被当作字符串使用时调用,例如在 echo 语句中。
  12. __invoke(): 当尝试将对象当作函数调用时执行。
  13. __set_state($array): 当调用 var_export() 且返回的结果被执行时调用。
  14. __clone(): 当对象被克隆时调用。

这些魔术方法提供了对对象生命周期中各种事件的控制,以及对对象行为的定制化。正确和恰当地使用这些方法可以使你的代码更加健壮和灵活

掌握PHP魔术方法分为触发时机--->功能--->参数-->返回值

最低要求:起码知道触发时机,不然对之后pop链的学习影响会很大

很感谢陈腾老师的教导!

接下来我会带领大家一一学习PHP魔术方法

接下来都会是代码加解释的形式和大家一起·学习,

1.——construct()

<?php
highlight_file(__FILE__);
class User {
    public $username;
    public function __construct($username) {
        $this->username $username;
        echo "触发了构造函数1次" ;
    }
}
$test = new User("benben");
$ser serialize($test);
unserialize($ser);

?>

输出:触发了构造函数1次

这里是先定义一个类User,下面的public是全局变量的意思,这里提一下,如果使用的是private,那就是属于一个私有属性,也就是说你只能在User这个类里面使用,如果你在外面调用了它,肯定是不行的。接下来public function __construct($username) {
        $this->username $username;
        echo "触发了构造函数1次" ;
    }这里就是一个魔术方法,

换句话来说就是user这个类里面有username,和一个魔术方法,后面的代码就是调用user这个类里面的属性而已

搞懂了代码就好说了!$test = new User("benben");这里是实例化对象,所以只会在这行代码触发,输出“触发了构造函数1次”

这个__construct()魔术方法很简单

触发时机:实例化对象时会触发比如($test = new User("benben");)这里就时实例化对象

功能就是:提前清理不必要的内容

参数:非必要

返回值:

2.__destruct()

在对象的所有的引用被删除或者当对象被显示销毁时执行的魔术方法

比如:<?php
highlight_file(__FILE__);
class User {
    public function __destruct()
    {
        echo "触发了析构函数1次"."<br />" ;
    }
}
$test = new User("benben");
$ser serialize($test);
unserialize($ser);

?>
触发了析构函数1次
触发了析构函数1次

__destruct()

触发时机:对象引用完成或对象被销毁;反序列化之后

功能:

参数:

返回值:

来到题目:

<?php
highlight_file
(__FILE__);
error_reporting(0);
class 
User {
    var 
$cmd "echo 'dazhuang666!!';" ;
    public function 
__destruct()
    {
        eval (
$this->cmd);
    }
}

$ser $_GET["benben"];
unserialize($ser);

拿到这道题目,就直接徒手构造就好了,benben=O:4:"User":1:{s:3:"cmd";s:13:"system('id');";}

首先是object:User对应的是四个字符,里面只有1个成员属性,最后的“;”不要忘记。

直接拿下,这里直接反序列化的时候就已经触发了——dstruct()

3._sleep()

触发时机:_slee[()先执行;序列化之后再执行,也就是序列化前调用

功能:

参数:

返回值:

<?php
highlight_file(__FILE__);
class User {
    const SITE 'uusama';
    public $username;
    public $nickname;
    private $password;
    public function __construct($username$nickname$password)    {
        $this->username $username;
        $this->nickname $nickname;
        $this->password $password;
    }
    public function __sleep() {
        return array('username''nickname');
    }
}
$user = new User('a''b''c');
echo serialize($user);
?>

O:4:"User":2:{s:8:"username";s:1:"a";s:8:"nickname";s:1:"b";}

这串代码的意思是一个对象user,还有它的对应属性。

接下来直接_construct魔术方法,因为最下面new User会触发

这个魔术方法,但是后面的sleep遇到serialize又会触发魔术方法_sleep(),这里先触发——construct(),(在实例化前触发)并且把username,nickname,password,为别赋值a,b,c

这里本来应该输出的是三个参数的,但是后面的sleep又触发魔术方法,结果password就不输出

4._wakeup()

这个在做反序列化unserialize()之前触发

触发时机:这个在做反序列化unserialize()之前触发

功能:

参数:

返回值:返回void

<?php
highlight_file
(__FILE__);
error_reporting(0);
class 
User {
    const 
SITE 'uusama';
    public 
$username;
    public 
$nickname;
    private 
$password;
    private 
$order;
    public function 
__wakeup() {
        
system($this->username);
    }
}

$user_ser $_GET['benben'];
unserialize($user_ser);
?>

?benben=O:4:”User”:1:{s:8:”username”;s:2:”id”;}

这里构造1个就好,因为_wakeup()过后就只调用username,其他几个属性就没有必要写了

Ps:反序列化里面对字符串包裹就只能使用双引号,单引号不识别

5._tostring()

触发时机:把对象被当成字符串调用

功能:

参数:

返回值:

<?php
highlight_file(__FILE__);
error_reporting(0);
class User {
    var $benben "this is test!!";
         public function __toString()
         {
             return '格式不对,输出不了!';
          }
}
$test = new User() ;
print_r($test);
echo "<br />";
echo $test;
?>
User Object ( [benben] => this is test!! )
格式不对,输出不了!(这个命令是 $test)所触发的

把类User实例化并且赋值给$test,此时的$test是个对象,调用对象可以使用print_

或者是var_dump

但是如果使用echo或者print只能调用字符串的方式去调用对象,即把对象当成字符串使用,此时自动触发tostring()

也就是说后面的echo $test直接当成字符串输出了,这里会触发魔术方法tostring()

6._invoke()

触发时机:把对象被当成函数调用

功能:

参数:

返回值:

<?php
highlight_file(__FILE__);
error_reporting(0);
class User {
    var $benben "this is test!!";
         public function __invoke()
         {
             echo  '它不是个函数!';
          }
}
$test = new User() ;
echo $test ->benben;
echo "<br />";
echo $test() ->benben;
?>
this is test!!
它不是个函数!

其实跟tostring差不多,就是(echo $test() ->benben)这里直接把它当成函数输出导致了魔术方法触发

7._call()

触发时机:调用了一个根本不存在的方法

功能:

参数:2个参数$arg1,$arg2

返回值:调用的不存在的方法的名称和参数

<?php
highlight_file(__FILE__);
error_reporting(0);
class User {
    public function __call($arg1,$arg2)
    {
        echo "$arg1,$arg2[0]";
          }
}
$test = new User() ;
$test -> callxxx('a');
?>

输出:callxxx,a

$test =new User()这句话是把new User()实例化成为一个对象给$test,接下来从test调用出来一个方法callxxx,并且给他传了个参数是a,但是这里根本没有callxxx,所以做不到,这里就触发了魔术方法

$arg1是方法,$arg2是参数

8._callstatic()

触发时机:静态调用或调用成员常量时使用

功能:

参数:2个参数$arg1,$arg2

返回值:调用的不存在的方法的名称和参数


<?php
highlight_file(__FILE__);
error_reporting(0);
class User {
    public function __callStatic($arg1,$arg2)
    {
        echo "$arg1,$arg2[0]";
          }
}
$test = new User() ;
$test::callxxx('a');
?>

callxxx,a

这里跟_call()差不多一样的,只不过这个是静态调用(比如$test::callxxx('a');)时使用而已,不是静态调用就不会触发,你可以把::改一下,看看别的还会不会触发


9.__get()

触发时机:调用的成员属性不存在

功能:

参数:

返回值:不存在的成员属性的名称

<?php
highlight_file(__FILE__);
error_reporting(0);
class User {
    public $var1;
    public function __get($arg1)
    {
        echo  $arg1;
    }
}
$test = new User() ;
$test ->var2;
?>

输出:
var2

这里其实就是少了一个参数var2,但是$test ->var2;这里却要输出var2,所以就会触发get()魔术方法,自动帮你添加一个var2上去

10._set()

触发时机:给不存在的成员属性赋值

功能:

参数:

返回值:不存在的成员属性的名称和赋的值

<?php
highlight_file(__FILE__);
error_reporting(0);
class User {
    public $var1;
    public function __set($arg1 ,$arg2)
    {
        echo  $arg1.','.$arg2;
    }
}
$test = new User() ;
$test ->var2=1;
?>

输出:
var2,1

11._isset()

对一个被保护的属性或者根本就不存在的属性,或者私有属性

触发时机:对不可访问属性使用isset()或empty()时,__isset()就会被调用

功能:

参数:

返回值:不存在的成员属性的名称

<?php
highlight_file(__FILE__);
error_reporting(0);
class User {
    private $var;
    public function __isset($arg1 )
    {
        echo  $arg1;
    }
}
$test = new User() ;
isset($test->var);
?>
输出:
var

比如这段代码,因为这里的var只能在当前类中使用,因为这是一个私有属性,你出来后调用肯定不可以,这里一定会触发——isset()魔术方法,最终顺利输出var

12._unset()

触发时机:对不可访问属性使用__unset()时

功能:

参数:

返回值:不存在的成员属性的名称

<?php
highlight_file(__FILE__);
error_reporting(0);
class User {
    private $var;
    public function __unset($arg1 )
    {
        echo  $arg1;
    }
}
$test = new User() ;
unset($test->var);
?>

输出:
var

13._clone()

触发时机:使用clone关键字拷贝完成一个对象后,新对象会自动调用定义的魔术方法__clone()

就是说使用clone()克隆对象完成后,就会触发魔术方法__clone()

功能:

参数:

返回值:

<?php
highlight_file(__FILE__);
error_reporting(0);
class User {
    private $var;
    public function __clone( )
    {
        echo  "__clone test";
          }
}
$test = new User() ;
$newclass = clone($test)
?>

输出:
__clone test

真心希望我的文章能够让大家有所收获!

总结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1342949.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SourceTree的安装和使用

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、安装&#xff1a;二、使用步骤1.获取地址2.放入sourceTree 3.点击推送 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 简单讲解一…

F12开发者工具如何找到对应接口

Web问题定位 1、进入 NetWork页面2、点击Fetch/XHR&#xff0c;这里可以看到页面发起的接口3、找到出问题的接口4、NetWork页面怎么看接口详情5、问题定位 最常用的定位前后端问题的方法。即&#xff1a;一般用来查看是后端返回给前端的数据有误&#xff0c;还是前端显示有误。…

【27.5K⭐】Spacedrive:功能强大且便捷的跨平台文件管理器

【27.5K⭐】Spacedrive&#xff1a;功能强大且便捷的跨平台文件管理器 在日常生活和工作中&#xff0c;我们经常需要使用不同的设备和云存储服务来存储和管理我们的文件。然而&#xff0c;这样做往往会导致文件的分散、重复和混乱&#xff0c;给我们带来不便和困扰。那么&…

免费在线客服软件推荐:经济实用的客户沟通解决方案

好用的在线客服软件是企业是必不可少的工具&#xff0c;他让企业流程更流畅高效&#xff0c;让客户服务更完善优质。市场上的在线客服软件有很多&#xff0c;说着免费使用的软件也不在少数。今天小编就来推荐一款免费在线客服软件。 不过&#xff0c;我们选择免费在线客服软件…

如何让python在手机上运行,python程序在手机上运行

大家好&#xff0c;给大家分享一下python怎么在手机上运行爱心代码&#xff0c;很多人还不知道这一点。下面详细解释一下。现在让我们来看看&#xff01; 1. 写在前面的话 天天都在PC端运行Python代码的我&#xff0c;今天突然灵光一现&#xff0c;想着是不是能够在移动端运行P…

R503S指纹识别模块的指令系统(一)

1.采集指纹图像 GetImage&#xff08;0x01&#xff09; 功能说明&#xff1a;探测手指&#xff0c;探测到后录入指纹图像存于 ImageBuffer&#xff0c;并返回录入成功确认码&#xff1b;若探测不到手指&#xff0c;直接返回无手指确认码(模块对于每一条指令都快速反应&#xf…

day3双指针

输入一字符串&#xff0c;然后将该字符串中的单词分割开来 #include <iostream> #include <string.h> using namespace std; int main() {char str[1000];gets(str);int nstrlen(str);for(int i0;i<n;i){int ji;while(str[j]! &&j<n) j;for(int ki;k…

从零开始部署CTF题目环境(docker容器)

本教程将教会大家如何安装一台可以部署docker容器形式的CTF题目的CentOS服务器。 操作步骤 1-下载操作系统镜像文件 虚拟操作系统&#xff1a;CentOS 8 &#xff08;CentOS 9 毛病多&#xff0c;先不装&#xff09; 镜像文件下载地址&#xff0c;点击X86_64即可 CentOS St…

邮件营销最佳时段:提升邮件打开率与转化率的策略

在如今数字时代&#xff0c;电子邮件营销已成为企业推广及与客户互动的有效途径。但是&#xff0c;一个普遍的现象是&#xff1a;何时发送电子邮件才能更合理&#xff1f;本文将探讨电子邮件营销的出色推送机会&#xff0c;并提供一些有用的提议&#xff0c;以帮助企业更好地规…

以元旦为题的诗词(二)

都放假了吧&#xff0c;都有空了吧&#xff0c;可坐下来好好学学诗词&#xff0c;好好写些诗词了吧&#xff0c;我先来几首&#xff0c;你实在不行&#xff0c;去百度或者小程序搜索《美诗计》写一写 元旦 去年元日落寒灰&#xff0c;今岁清明在此杯 老眼看书如梦寐&#xff…

ALSA学习(4)——Control设备的创建

参考博客&#xff1a; https://blog.csdn.net/DroidPhone/article/details/6409983 &#xff08;下面的内容基本是原博主的内容&#xff0c;我只是修改了一些格式之类的&#xff09; 文章目录 一、Control接口二、Controls的定义三、Control的名字四、访问标志&#xff08;ACC…

运维分享|MySQL的字符集(一)

&#x1f4eb; 作者简介&#xff1a;「六月暴雪飞梨花」&#xff0c;专注于研究Java&#xff0c;就职于科技型公司后端工程师 &#x1f3c6; 近期荣誉&#xff1a;华为云云享专家、阿里云专家博主、 &#x1f525; 三连支持&#xff1a;欢迎 ❤️关注、&#x1f44d;点赞、&…

Servlet获取前端请求的参数和中文乱码的解决方案

目录 1.Servlet获取前端请求的参数 1.1创建jsp 1.2构建servlet实例 1.3配置web.xml 2.中文乱码的解决方案 2.1请求时候的乱码问题 2.2响应时候中文乱码的问题 学好Servlet必须紧紧围绕着请求和响应这两个概念。 下面开始写在请求的时候前端带数据到servlet里面&#xff…

DP进阶之路——01背包问题

题目链接&#xff1a;题目页面 小明是一位科学家&#xff0c;他需要参加一场重要的国际科学大会&#xff0c;以展示自己的最新研究成果。他需要带一些研究材料&#xff0c;但是他的行李箱空间有限。这些研究材料包括实验设备、文献资料和实验样本等等&#xff0c;它们各自占据不…

【数据结构】C语言实现双链表的基本操作

双链表及其基本操作的实现 导言一、单链表与双链表二、双链表类型的创建三、双链表的初始化四、双链表的创建五、双链表的遍历六、双链表的查找七、双链表的插入八、双链表的删除结语 导言 大家好&#xff0c;很高兴又和大家见面啦&#xff01;&#xff01;&#xff01; 经过…

SpringBoot+modbus4j实现ModebusTCP通讯读取数据

场景 Windows上ModbusTCP模拟Master与Slave工具的使用&#xff1a; Windows上ModbusTCP模拟Master与Slave工具的使用-CSDN博客 Modebus TCP Modbus由MODICON公司于1979年开发&#xff0c;是一种工业现场总线协议标准。 1996年施耐德公司推出基于以太网TCP/IP的Modbus协议&…

Linux - 设置虚拟机和主机IP在同一网段(桥接)

1.查看主机ip地址等相关信息。 ipconfig -all 2.设置虚拟网络编辑器 打开虚拟网络编辑器 设置虚拟网络编辑器&#xff0c;设置为桥接模式。&#xff08;记得以管理员方式打开VMware&#xff09;。 3.修改虚拟机网卡文件 查看虚拟机ip,我们的目标是将其修改为与主机同一网段…

JAVA电商平台 免 费 搭 建 B2B2C商城系统 多用户商城系统 直播带货 新零售商城 o2o商城 电子商务 拼团商城 分销商城

在数字化时代&#xff0c;电商行业正经历着前所未有的变革。鸿鹄云商的saas云平台以其独特的架构和先进的理念&#xff0c;为电商行业带来了全新的商业模式和营销策略。该平台涉及多个平台端&#xff0c;包括平台管理、商家端、买家平台、微服务平台等&#xff0c;涵盖了pc端、…

合并区间(LeetCode 56)

文章目录 1.问题描述2.难度等级3.热门指数4.解题思路参考文献 1.问题描述 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输…

虚拟机域环境的搭建

开始准备两台虚拟机Windows Server 2016和Windows10. Windows Server 2016的配置&#xff1a; 1.要用Administrator管理员&#xff0c;首先创建一个Administrator管理员 在此就可以创建一个新用户 然后退出登录就可以了。 2.开始环境的搭建 第一步&#xff1a; 第二步&…