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

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.mfbz.cn/a/278043.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

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

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

这本书没有一个公式,却讲透了数学的本质!

这本书没有一个公式&#xff0c;却讲透了数学的本质&#xff01; 《数学的雨伞下&#xff1a;理解世界的乐趣》。一本足以刷新观念的好书&#xff0c;从超市到对数再到相对论&#xff0c;娓娓道来。对于思维空间也给出了一个更容易理解的角度。 作者&#xff1a;米卡埃尔•洛奈…

毫米波雷达:从 3D 走向 4D

1 毫米波雷达已广泛应用于汽车 ADAS 系统 汽车智能驾驶需要感知层、决策层、执行层三大核心系统的高效配合&#xff0c;其中感知层通过传感器探知周围的环境。汽车智能驾驶感知层将真实世界的视觉、物理、事件等信息转变成数字信号&#xff0c;为车辆了解周边环境、制定驾驶操…

Element UI之el-tabs的样式修改字体颜色、下划线、选中/未选中

目录 默认样式 修改默认字体颜色&#xff1a; 修改鼠标悬浮/选中字体颜色&#xff1a; 去掉长分割线并修改下划线颜色 完整代码 默认样式 注意事项&#xff1a;一定要在 <style scoped>不然修改的样式不会覆盖生效 修改默认字体颜色&#xff1a; ::v-deep .el-tabs__…

Java虚拟机中的垃圾回收

2 垃圾回收 2.1 判断一个对象是否可回收 2.1.1 引用计数法 如果一个对象被另一个对象引用&#xff0c;那么它的引用计数加一&#xff0c;如果那个对象不再引用它了&#xff0c;那么引用计数减一。当引用计数为 0 时&#xff0c;该对象就应该被垃圾回收了。 但是下面这种互相…

2023,平安!2024,最诚挚的祝福送给诸君!

☞ ░ 前往老猿Python博客 ░ https://blog.csdn.net/LaoYuanPython 时光荏苒&#xff0c;流年如水&#xff0c;一载忙碌&#xff0c;收获寥寥&#xff0c;然家人安康&#xff0c;生活安稳&#xff0c;尚有几分欣慰。 值此岁末之时&#xff0c;CSDN举行年度征文&#xff0c;适逢…

独立站如何优化网页加载速度

对于跨境电商独立站而言&#xff0c;流量是跨境电商业务的重中之重&#xff0c;由于独立站并不自带流量&#xff0c;非常依赖于谷歌搜索引擎自然流量&#xff0c;以及付费广告流量。 但随着付费流量价格日益水涨船高&#xff0c;为了摆脱对付费流量的依赖&#xff0c;相信广大…

很实用的ChatGPT网站——httpchat-zh.com

很实用的ChatGPT网站——http://chat-zh.com/ 今天介绍一个好兄弟开发的ChatGPT网站&#xff0c;网址[http://chat-zh.com/]。这个网站功能模块很多&#xff0c;包含生活、美食、学习、医疗、法律、经济等很多方面。下面简单介绍一些部分功能与大家一起分享。 登录和注册页面…

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

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

口罩佩戴监测识别摄像机

口罩佩戴监测识别摄像机是一种应用于公共场所的智能监控设备&#xff0c;旨在监测人们是否正确佩戴口罩。这种摄像机使用先进的图像识别技术&#xff0c;能够准确辨识出人们的面部&#xff0c;并判断是否佩戴口罩。该技术可以用于各种场所&#xff0c;如火车站、机场、商场、学…

大模型中的LM-BFF

LM-BFF paper: 2020.12 Making Pre-trained Language Models Better Few-shot Learners Prompt: 完形填空自动搜索prompt Task: Text Classification Model: Bert or Roberta Take Away: 把人工构建prompt模板和标签词优化为自动搜索 LM-BFF是陈丹琦团队在20年底提出的针对…

Android笔记(二十二):Paging3分页加载库结合Compose的实现网络单一数据源访问

Paging3 组件是谷歌公司推出的分页加载库。个人认为Paging3库是非常强大&#xff0c;但是学习难点比较大的一个库。Paging3组件可用于加载和显示来自本地存储或网络中更大的数据集中的数据页面。此方法可让移动应用更高效地利用网络带宽和系统资源。在具体实现上&#xff0c;Pa…

YBM41567/4A 20V1.0A线性锂电池充电管理芯片

YBM41567/4A 20V1.0A线性锂电池充电管理芯片 概述&#xff1a; YB4156/7/4A是一款狸电池充电管理芯片&#xff0c;集成涓流、恒流、恒压三段式线性充电管理&#xff0c;符合锂电池安全充电规范。充电输入耐压高达24V,充电电流高至1.0A,可通过片外电阻配置。YB4156/7/4A集成防…

{MySQL} 数据库约束 表的关系 新增删除 修改 查询

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、数据库约束1.1约束类型&#xff1a;1.2 NULL约束1.3unique 唯一约束1.4 DEFAULT&#xff1a;默认值约束1.5 PRIMARY KEY&#xff1a;主键约束1.6 FOREIGN K…

C++ 类和对象 (上)

类的引入&#xff1a; 由于C语言是面向过程的编程语言&#xff0c;我们在完成一件事的时候通常习惯将一件事拆分成一个一个小过程来实现&#xff0c;而到了C就习惯将一件事分成不同的模块&#xff0c;交给不同的对象来处理&#xff0c;每一个对象中承载着数据类型和函数。 &am…

PO 发布SAP SProxy->外围系统 WebService

通信概览图 外围系统与PO、SAP的请求响应通信过程大致可以用下图描述 &#xff08;个人整理所得&#xff0c;可能有误&#xff0c;欢迎指正&#xff09; 1. 前期准备 1.1 外围系统提供WebService接口 以A系统的RFC发布WebService接口 RFC发布WebService接口 获取到WSDL地…

【操作系统】不同操作系统内核架构分析

一、内核架构与操作系统性能之间的关系的分析 1. 适用性和专业化&#xff1a; 不同的内核架构往往会有不同的设计目标和优化点。例如&#xff0c;实时操作系统&#xff08;RTOS&#xff09;和通用操作系统&#xff08;像Linux或Windows&#xff09;在设计时就有不同的重点&am…

ESP32:整合存储配网信息和MQTT笔记

文章目录 1.给LED和KEY的所用IO增加配置项1.1 增加配置文件1.2 修改相应的c源码 2. 把mqtt\tcp的工程整合到一起2.1 在何处调用 mqtt_app_start() 3. 测试MQTT4. 完整的工程源码 有一段时间没有玩ESP32&#xff0c;很多知识点都忘记了。今天测试一下MQTT&#xff0c;做个笔记。…

循环冗余效验码的计算方法

循环冗余效验码的计算方法 G&#xff08;x&#xff09;&#xff1a; 在了解计算方法之前我们首先要明白G&#xff08;x&#xff09;表明的意思&#xff0c;这一步非常重要&#xff01; 例如&#xff0c;G&#xff08;x&#xff09; x^3 x^2 1 &#xff0c;该式子表明的编…

【每天一个早下班技巧】NPM发包流程

发包流程 step1&#xff1a;设置包发布地址 参考资料 // 1.在package.json中设置发布地址 "publishConfig":{"registry":"http://registry.npm.xxx.com" }//2.设置别名 alias ynpm"npm --registryhttp://registry.npm.xxx.com" ynp…
最新文章