PHP基础知识点【十一】魔术方法

掌握PHP魔术方法的全面应用指南 本文还有配套的精品资源,点击获取 简介:PHP中的魔术方法是当特定条件满足时自动执行的特殊函数。它们以双下划线开头,并在对象的生命周期中的关键时刻被自动调用。本篇内容将详细解析包括构造函数、析构函数、运行时方法动态添加、属性动态访问和设置、序列化控制、对象字符串表示以及对象作为函数调用等在内的多种魔术方法,并展示它们在实际编程中的应用场景。通过这些方法的运用,开发者能提升类... 阅读详情

PHP 将所有以 __(两个下划线)开头的类方法保留为魔术方法。所以在定义类方法时,除了上述魔术方法,建议不要以双下划线前缀。这些魔术方法使用的时候不需要用户自己去调用,而是在特定的情况下会被自动调用。

【1】__construct()与__destruct()

       PHP中允行开发者在一个类中定义一个方法作为构造方法。具有构造方法的类会在每次创建新对象时先调用此方法,所以非常适合在使用对象之前做一些初始化工作。触发调用它的情况就是创建对象new的时候。另外析构方法会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。

【2】__set()与 __get()

      在面向对象思想中,一般要对属性进行封装,这样类外对象不能直接进行访问或者修改,但是这样的话,我们另外需要定义一个类似setValue()这样公有的方法接口,从而简介的为私有属性赋值。但是如果私有属性比较多,那么我们还需要对每一个属性去写这样的公有方法,比较繁琐。那么我们可以用魔术方法__set()去解决这个问题。该方法能够控制在对象外部为非公有的成员进行属性赋值。需要用户在声明的类的时候去实现这个方法,才可以在设置非公有属性下去调用。如果没有写这个方法,而去直接修改非公有属性会报错。

#在给不可访问属性赋值时,__set() 会被调用。
public __set ( string $name , mixed $value ) : void

       如果在类中声明了__get()方法。则可以在对象外部直接获取非公有属性。当然你也可以在方法中设定一些规则不能所有的都能去访问。它 有一个必选参数,必须要传入非公有属性的属性名,然后函数会返回一个值。

#读取不可访问属性的值时,__get() 会被调用。
public __get ( string $name ) : mixed	

【3】__isset()与__unset()

       我们知道PHP内置函数中也有一个isset(),用来测定变量是否存在,传入一个变量作为参数如果存在返回true,否则返回false。那么我们也可以用该函数去测定对象的成员属性,不过这个属性必须是公有的,所以如果是私有的,那就不行了。不过PHP也提供了对应的魔术方法。需要用户在类中声明__isset()方法。这样当在类的外部使用isset()函数或者empty()函数来测定对象中的非公有属性的时候,就会自动调用魔术方法来进行测定。

#当对不可访问属性调用 isset() 或 empty() 时,__isset() 会被调用。
public __isset ( string $name ) : bool

       另外我们也知道有一个unset()内置函数,用来删除指定的变量,需要传入变量名。同样的魔术方法__unset()的作用也是为了可以在类外删除对应的非公有属性。当在类外使用unset()删除某个不可访问的属性,就会自动调用魔术方法进行删除。

#当对不可访问属性调用 unset() 时,__unset() 会被调用。
public __unset ( string $name ) : void

看一下下面的例子吧:

class Person{
    private   $name;
    protected $age;
    public    $sex;
    function __construct($name='',$age=18){#构造方法也是一种魔术方法
        $this->name = $name;
        $this->age  = $age;
    }
    public function __set($name,$value){#设置非公有的属性 会被调用
        if($name = 'age')   $this->$name = $value;#设置只能修改age
    }
    public function __get($name){#获取非公有的属性 会被调用
        echo $this->$name;
    }
    public function __isset($name){#判断某个非公有的属性时候,会被调用
        echo "<br/>Is '$name' set?  ";
        return isset($this->$name);
    }
    public function __unset($name){#销毁某个非公有的属性时候,会被调用
        echo "<br/> Unsetting '$name' ";
        unset($this->$name);//没有返回值
        echo ' OK! ';
    }
    public function __destruct(){#析构方法 也是魔术方法
        echo '<br/>Bye!....<br/>';
    }
}
$obj = new Person('tacks');//实例化的时候,会自动调用魔术构造方法 顺便传入参数进行初始化 
var_dump($obj);
$obj->name = 'AAA';//这里进行设置 但是不会起作用,因为我们在__set方法里面设定只能修改age
$obj->age  = 20;//设置私有属性  会自动调用到魔术方法__set
echo $obj->name;//获取私有属性  会自动调用到魔术方法__get
echo isset($obj->age)?'Yes':'No';#判断一个属性,会自动调用到魔术方法__isset
echo '<br/>';
echo isset($obj->sex)?'Yes':'No';#判断一个属性,是公有的属性,没有调用到魔术方法
unset($obj->age);//没有返回值 会调用一个魔术方法__unset()
echo '<br/>Kill!';
#程序结束,对象销毁的时候,会自动调用魔术析构方法。
/*
object(Person)[1]
  private 'name' => string 'tacks' (length=5)
  protected 'age' => int 18
  public 'sex' => null
tacks
Is 'age' set? Yes
No
Unsetting 'age' OK!
Kill!
Bye!....
*/

【4】__toString()

我们知道在使用实例化类产生的对象,它实际上是对象引用,即指针,存放在堆空间的首地址变量。我们不能直接用echo去输出对象的值,这样会报错。如果在定义的类中添加__toString()魔术方法,而且该方法必须返回一个字符串。则直接去输出对象引用的时候就不会报错,而是自动调用该方法。

#__toString() 方法用于一个类被当成字符串时应怎样回应。
#例如 echo $obj; 应该显示些什么。此方法必须返回一个字符串
#否则将发出一条 E_RECOVERABLE_ERROR 级别的致命错误。
public __toString ( void ) : string
//_toString 必须返回一个字符串。
class Person{
    private $mine = 'Tacks';
    public function __toString(){#声明这个魔术方法
        return $this->mine;#必须返回一个字符串
    }
}
$obj = new Person;
echo $obj;#在被当作一个字符串的时候,自动调用魔术方法

【5】__call()与__callStatic()

       如果对象调用了一个不存在的方法,那么系统一定会报错,并且退出程序不能继续执行。在PHP中,可以在类中添加一个魔术方法__call(),那么在调用对象中不存在的方法的时候,就会自动调用该方法,并且程序会继续执行,不受影响。所以我们可以接触该方法提示用户。这个魔术方法中有两个参数,第一个参数用来接收,调用不存在的方法名,第二个参数,则是以数组的形式接收不存在方法的参数列表。

       PHP5.3后还有一个跟它很像的一个魔术方法__callStatic(),用于调用不存在的静态方法的时候,会被调用。

#在对象中调用一个不可访问方法时,__call() 会被调用。
public __call ( string $name , array $arguments ) : mixed

#在静态上下文中调用一个不可访问方法时,__callStatic() 会被调用。
public static __callStatic ( string $name , array $arguments ) : mixed
class Person{#定义一个类
    public function __call($fun,$args){#实现魔术方法__call()
        echo 'Calling  Object Method :',$fun,'()  and args: ',implode(', ',$args),'<br/>';
    }
    public static function __callStatic($fun,$args){
        echo 'Calling  Static Method :',$fun,'()  and args: ',implode(', ',$args),'<br/>';
    }
    public static function run(){
        echo 'Running <br/>';
    }
}
$obj = new Person;
$obj->say('name','age','sex');#当方法不存在的时候,会触发到__call()方法
Person::say('name','age','sex');#当类的静态方法不存在的时候, 会触发到__callStatic()方法
$obj->run();#其实静态方法,也可以用对象进行调用
Person::run();#利用类名::方法名  调用存在的静态方法
/*
Calling Object Method :say() and args: name, age, sex
Calling Static Method :say() and args: name, age, sex
Running
Running 
*/

【6】类自动加载

     类的自动加载。在编写面向对象(OOP) 程序时,很多开发者为每个类新建一个 PHP 文件。 这会带来一个烦恼:每个脚本的开头,都需要包含(include)一个长长的列表。spl_autoload_register() 函数可以注册任意数量的自动加载器,当使用尚未被定义的类(class)和接口(interface)时自动去加载。通过注册自动加载器,脚本引擎在 PHP 出错失败前有了最后一个机会加载所需的类。

spl_autoload_register(function ($class_name) {
    require_once $class_name . '.class.php';
});
$obj1  = new A();
$obj2  = new B();

      另外还有一个魔术方法用来自动加载, __autoload(),这个方法不是在类中声明的,它是一个全局函数,如果这个函数存在,PHP会用一个参数去调用它,参数即类名。

//声明一个自动加载类的魔术方法
function __autoload($class){
    include($class.'.class.php');//加载类文件
}
$obj1 = new A();#实例化不存在的时候,会调用这个魔术方法
$obj2 = new B();

【7】__sleep()与__wakeup()

       序列化serialize() 函数会检查类中是否存在一个魔术方法 __sleep()。如果存在,该方法会先被调用,然后才执行序列化操作。此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称的数组。如果该方法未返回任何内容,则 NULL 被序列化,并产生一个 E_NOTICE 级别的错误。

       反序列化unserialize()函数 会检查是否存在一个 __wakeup()方法。如果存在,则会先调用该方法,预先准备对象需要的资源。它经常用在反序列化操作中,例如重新建立数据库连接,或执行其它初始化操作。

public __sleep ( void ) : array
__wakeup ( void ) : void

【8】__invoke()

当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。

class Demo{
    function __invoke($k){#声明魔术方法
        var_dump($k);//输出参数
    }
}
$obj = new Demo;
$obj(99);//int 99 //在对象上用函数的方法,会自动调用__invoke()
var_dump(is_callable($obj));//boolean true//函数用于检测函数在当前环境中是否可调用。

【9】__set_state()

      自 PHP 5.1.0 起当调用 var_export() 导出类时,此静态方法会被调用。本方法的唯一参数是一个数组,其中包含按 array('property' => value, ...) 格式排列的类属性。

# static __set_state ( array $properties ) : object
    
class Person{
    public $name;
    static public  function __set_state($arr){
        $obj = new Person;
        $obj->name = $arr['name'];
        return $obj;
    }
}
$tacks = new Person;
$tacks->name = 'Tacks';
//把字符串按照 PHP 代码来计算。该字符串必须是合法的 PHP 代码,且必须以分号结尾
eval('$test = ' . var_export($tacks, true) . ';');
#会触发__set_state魔术方法
var_dump($test);

【10】对象克隆

      PHP中的对象模型是通过引用调用对象的,有时候我们需要调用对象的一个副本,改变原来的对象的时候,不希望影响到副本。如果用new一个新对象再去赋值什么的比较繁琐。我们可以用clone去克隆一个对象,克隆后连个对象互补干扰,但是他们的成员属性和方法是一样的。克隆不经过构造方法比较快速。

      对象复制可以通过 clone 关键字来完成(如果可能,这将调用对象的魔术方法)即对象中的 __clone() 方法,它不能被直接调用。当对象被复制后,PHP 5 会对对象的所有属性执行一个浅复制(shallow copy)。所有的引用属性 仍然会是一个指向原来的变量的引用。

class Money{
    public $name;
    public function __construct($name){#构造方法
        echo "CONSTRUCT<br/>";
        $this->name = $name;
    }
    public function intro(){
        echo 'I am ',$this->name,' Money<br/>';
    }
    public function __clone(){#魔术方法 对象克隆的时候会被调用
        echo 'CLONE<br/>';
    }
}
$p1 = new Money('Sun Wukong');//CONSTRUCT
$p1->intro();//I am Sun Wukong Money
echo '<hr/>';
$p2 = clone $p1;#克隆了一份 ,不执行构造方法,比较快 会触发魔术方法__clone()
$p2->intro();//I am Sun Wukong Money

【小结】

  1. __construct()构造方法完成类实例化的时候一些操作,__destruct()析构方法在对象销毁的前完成一些操作。

  2. __set()在对象外部为非公有的成员进行属性赋值 ,__get()在对象外部访问非公有成员属性。

  3. __isset()类的外部使用isset()或者empty()函数来测定对象中非公有属性。__unset()删除某个不可访问的属性

  4. __toString()魔术方法直接去输出对象的引用

  5. __call()在调用对象中不存在的方法的时候;callStatic()调用不存在的静态方法的时候。

  6. 引入类的自动加载利用spl_autoload_register()函数,或者__autoload()魔术方法。

  7. __sleep()序列化对象的时候,__wakeup()反序列化对象的时候调用。

  8. 当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。

  9. __set_state() ,当调用 var_export() 导出类时,此静态方法会被调用。

  10. __clone() 用于克隆对象的时候会被调用 。

华为星闪SLE实战:手把手教你用HarmonyOS开发智能家居控制应用(附完整代码) 本文详细介绍了如何利用华为星闪SLE技术,结合HarmonyOS开发智能家居控制应用。通过对比传统无线技术,阐述了星闪SLE在低时延、高可靠性和高并发方面的优势,并提供了从环境搭建、设备发现、连接管理到核心控制代码的完整实战教程,帮助开发者快速上手这一无线短距通信技术。 阅读详情

相关推荐

长短期记忆网络(Long Short-Term Memory networks, LSTM)

如何简单的理解LSTM——其实没有那么复杂:

weixin_39910711的博客 2万+

PHP POP链小结,梳理一下__destruct魔术方法

pop链小结

m0_73606240的博客 1118

斯坦福HumanPlus机器人核心技术解析:从HST强化学习框架到HIT模仿学习的实现路径

本文深入解析了斯坦福HumanPlus人形机器人的核心技术实现路径。其核心在于HST强化学习框架与HIT模仿学习架构的协同:HST作为“小脑”,通过rsl_rl框架在仿真中训练稳健的低级运动控制;HIT作为“大脑”,基于改进的Transformer架构学习高级任务规划。文章详细拆解了从算法原理、代码实现到硬件部署的全流程,为复现这一前沿机器人系统提供了实战指南。

weixin_29082143的博客 281

php 析构不执行,PHP析构方法 __destruct() 不触发的两个解决办法

本篇文章主要给大家介绍PHP 析构方法 __destruct() 不触发的两个解决办法。有时候在 PHP 里类循环引用时,会导致 __destruct() 不触发的问题,先上问题代码:...

weixin_42143221的博客 526

联想服务器ThinkSystemRAID阵列设置教程

关注我不迷路,全是干货! 以联想ThinkSystemSR530为例子进行示范。 开机点按【F1】 点击——【UEFI设置】 依次点击——【系统设置】——【存储】 点击——【RAID卡】 PS:本次服务器配置的是730-8i 阵列卡,按实际情况选中需要设置的阵列卡即可。 点击——【Main Menu】 点击——【Configuration Management】 点击——【Create Virtual Drive】 点击——【Select RAID Leve..

littlelotusK的博客 2万+

反序列化之魔术方法的浅学习

前言 学习反序列化,那么就需要首先掌握魔术方法的使用,本篇文章将尽可能详细的讲解反序列化的魔术方法,博主只是小白,如有问题还请各位师傅多多指点! 魔术方法 常见魔术方法有以下几种 __construct: 在创建对象时候初始化对象,一般用于对变量赋初值。 __destruct: 和构造函数相反,当对象所在函数调用完毕后执行。 __call:当调用对象中不存在的方法会自动调用该方法。 __get():获取对象不存在的属性时执行此函数。 __set():设置对象不存在的属性时执行此函数。 __toString

quan9i的博客 3571

手把手教你排查I2C通信故障:当上拉电阻配置不当会发生什么?

本文深入解析I2C通信中上拉电阻配置不当导致的常见故障,包括波形畸变和通信失败现象。通过示波器波形分析和系统化解决方案,帮助工程师快速诊断和优化I2C总线性能,特别适用于嵌入式系统和智能设备开发场景。

weixin_33725722的博客 341

php __destruct 有什么用,php 析构方法 __destruct 什么情况下执行

按照官方手册的描述,析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。代码演示如下class sf{public function __destruct(){echo __METHOD__ . PHP_EOL;}}$c1 = new sf;$c2 = $c1;echo 'unset $c2' . PHP_EOL;unset($c2);echo 'unset $c1' . PHP_...

weixin_31108679的博客 378

Linux系统安装部署Redis完整教程(图文详解)

最近需要在Linux服务器安装部署Redis,参考了网上很多的文章,比较零碎,所以我自己写了一篇完整的Redis安装部署文档,在部署Redis之前重装了我的华为服务器,就是为了给大家一步步阐述我的操作过程,配合图文进行讲解更加通俗易懂!

黄团团的个人博客 6692

【精品5万字图文详解】特征平台建设方案与最佳实践

关键词:特征工程、特征平台、特征存储、特征服务、机器学习、数据工程摘要:本文全面介绍了特征平台的建设方案与最佳实践,从特征工程的基本概念出发,深入剖析了特征平台的核心组件、架构设计和实现方法。文章通过生动的类比和实例,使读者能够轻松理解特征工程的重要性及特征平台如何解决企业在机器学习过程中面临的数据管理挑战。同时,详细探讨了主流开源特征平台的对比分析、系统设计要点、实际落地案例以及未来发展趋势,为企业构建高效特征平台提供了全面的指导和参考。想象一下,小明是一位热爱烹饪的小学生。有一天,他想做一道美味的菜肴送

AI天才研究院 952

析构函数 php,PHP中__destruct(),类的析构函数详解

PHP中把以两个下划线__开头的方法称为魔术方法(Magic methods),这些方法在PHP中充当了举足轻重的作用。PHP中__destruct(),类的析构函数通过《PHP中__destruct(),类的构造函数》讲解,现在我们已经知道了什么叫构造方法。那么与构造方法对应的就是析构方法。析构方法允许在销毁一个类之前执行的一些操作或完成一些功能,比如说关闭文件、释放结果集等。析构方法是PHP5...

weixin_39848998的博客 1453

【Windows Server 2019】邮件服务器配置与管理——安装及配置Winmail服务器(上)

博文介绍了如何安装邮件服务器 Winmail,如何配置Winmail,包括运行服务器,Winmail管理工具介绍和域名配置。

VMware, Windows, Linux, Cisco, Container, Kubernetes, Kali 2万+

PHP之魔术方法

ctf常用的魔术方法

errorr0 7442

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

PHP的魔术方法

‌PHP魔术方法是以双下划线__开头的一组特殊方法,用于在对象生命周期、属性访问、方法调用等场景中实现自动化操作。‌简化面向对象编程。

Daisy的博客 1048

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

PHP的类和魔术方法

PHP的类和魔术方法

duke_ding2的博客 1270

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

php的魔术方法

魔术方法:魔术方法是PHP面向对象中特有的特性。它们在特定的情况下被触发,都是以双下划线开头,你可以把它们理解为钩子,利用模式方法可以轻松实现PHP面向对象中重载(Overloading即动态创建类属性和方法)。魔术方法很多还是成对出现的,以下列出目前PHP中所有的模式方法。   以两个下划线开始,表示这些方法在php特定事件下将会被触发。这可能听起来有点自动魔法但是它真的很酷的,我们已经看过一

重口味码农 1227

php 的魔术方法有什么用,php魔术方法有什么用

(); echo $s->name; echo $s->age; A 小明 B 20 C 小明 20 D 报错误 三、简答题(共 20 分): 1、请列举五个 PHP 魔术方法函数,并说明各自的用法......PHP是什么--10秒了解PHP_计算机软件及应用_IT/计算机_专业资料。新浪微博是用什么程序(语言)写(开发)的?答案是PHP。 PHP是什么,10秒让你了解PHP的强大。 ...

weixin_29091837的博客 421

php魔术常量、超全局变量和魔术方法汇总

php魔术常量、超全局变量、魔术方法汇总

清风朗月的博客 2086

php 魔术方法

PHP 将所有以 __(两个下划线)开头的类方法保留为魔术方法。所以在定义类方法时,除了上述魔术方法,建议不要以 __ 为前缀。 php版本:7.2.10 php 魔术方法构造方法:__construct析构方法:__destruct重载属性重载__set();__get();__isset();__unset();方法重载__call()__callStatic()序列化与反序列化魔术方...

Little bear's blog 1115

php魔术方法

今天儿面试,问我魔术方法是啥子,我母鸡 回家看了看,发现 就是php默认的,制定的几个方法,会在特殊情况下启动,和JAVA的构造函数一样 魔术方法有:__construct(), __destruct (), __call(), __callStatic(),__get(), __set(), __isset(), __unset (), __sleep(), __wakeup(), __t...

NESNES的博客 289

php反序列化基础知识之魔术方法

php魔术方法

qq_42077227的博客 1356

PHP的魔术方法以及简单使用

背景 前几篇的关于服务提供者、Facade以及Contract中,我们经常会看到,在类文件中有一个共同的方法construct() ,并且是以__为头,这个呐,就是魔术方法 一、什么是魔术方法呐 首先要了解到魔术方法并不是laravel独有的,而且任务php应用中都可以使用 魔术方法是在PHP中声明的任何类中都可以使用的方法,它提供了在类中实现附加功能的方法 魔术方法永远不会被程序员调用 —— 实际上,PHP 将在后台调用该方法。这就是为什么它们被称为 “魔术” 方法 —— 因为它们从来没有被直接调用,但

snow_love_xia的博客 1033

深入理解 PHP 魔术方法

PHP 中的魔术方法是一些特殊的方法,它们以双下划线(__)开头,在特定的情况下会被自动调用。这些方法为类提供了强大的功能扩展,让开发者可以更灵活地控制对象的行为。

m0_57836225的博客 967

PHP基础及魔术方法

你可能会想复制一个新的窗口,保持所有属性与原来 的窗口相同,但必须是一个新的对象(因为如果不是新的对象,那么一个窗口中的改变就会影响到另一 个窗口)。还有一种情况:如果对象 A 中保存着对象 B 的引用,当你复制对象 A 时,你想其中使用的对 象不再是对象 B 而是 B 的一个副本,那么你必须得到对象 A 的一个副本。__set( $property, $value ) 方法用来设置私有属性, 给一个未定义的属性赋值时,此方法会被触 发,传递的参数是被设置的属性名和值。PHP 中,只有一个字符串运算符。

2301_82218779的博客 944

php的魔术方法 形象深入的理解它

问:对php来说,什么是魔术方法?为什么是方法而不是函数 答:魔术方法就是具有法术的方法,之所以叫方法而不叫函数,是因为大部分这些个功能体都是在对象上发挥作用,唯有两个特别的,至于这个方法是什么等会详细说一下。那魔术方法有什么法术呢?那就是他能在特定时刻发挥作用,好比一个定时炸弹,到那个时间上立马就炸(运行),没有商量的余地。 问:php有哪些魔术方法?都有什么在什么时候发挥作用?...

u012274988的博客 255
上一篇: PHP基础知识点【十】面向对象
下一篇: PHP字符串转义相关函数
Tacks
博客等级 码龄9年 37粉丝 97原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值