在PHP中,有一堆魔术方法,服务于类和对象。PHP虽然也是纯种的面向对象语言,但是之前的PHP还真不是,所以有一些面向对象的标准实现并不完善,比如重载。但是,我们可以通过一些魔术方法来弥补,例如__call()方法就可以用来实现重载。

话不多说,我们一个一个的来看。

__construct()和__destruct()

这两个是非常出名并且也是非常常用的魔术方法。__construct()是构造函数。在Java中,构造函数是与类名相同的方法名,而PHP在早期的版本中也是这样的,但从5以后改成了__construct()方法来实现,原因是当类名进行修改的时候,可以不用再去修改这个方法名了。当然,我们用与类名相同的方法名也是可以向下兼容的,不过最好不要这样用。

__destruct()方法是析构函数,不需要显式的调用,系统会自动调用这个方法。而且析构函数不需要参数,因为它不需要去调用嘛,系统自动调用的时候也是不会去带参数的。

public function __construct()
{
echo '构造函数' . PHP_EOL;
} public function __destruct()
{
echo '析构函数' . PHP_EOL;
}

__call()与__callStatic()

非常重要而且也是面试时经常会问到的魔术方法。它们俩的作用其实差不多,都是用于未定义的方法,当使用这些未定义的方法时就会进入这两个函数中。比如说我们调用$a->b();这个方法,但其实在$a的类模板中并没有b()方法,这时就会进入__call()方法进行处理。__callStatic()则是通过静态调用时如果没有定义对应的方法,就进入到__callStatic()方法中,如A::b(),并没有定义b()方法,这时就进入了__callStatic()中进行处理。

开头说道,__call()可以实现类似于Java中的函数重载的能力。函数重载其实就是同名的函数,但参数或返回值不同,在Java等强类型语言中可以方便的实现,但PHP是弱类型语言,无法准确的定位方法的重载,使用__call()方法其实也需要很多的判断,并不是非常的推荐一定要和Java一样的去实现函数重载。我们还是需要根据语言的特性来对业务功能进行深入的分析后再进行对应的实现。

在Laravel框架中,使用的Facade模式,也就是门面模式,核心代码就是使用了__callStatic()方法。有兴趣的小伙伴可以自行查看下Laravel的源码。

public function __call($name, $arguments)
{
echo '===call===' . PHP_EOL;
echo '未定义的方法找我' . PHP_EOL;
echo '您需要的是' . $name . ',参数是:';
print_r($arguments);
echo '===call===' . PHP_EOL;
} public static function __callStatic($name, $arguments)
{
echo '===callStatic===' . PHP_EOL;
echo '未定义的静态方法找我' . PHP_EOL;
echo '您需要的是' . $name . ',参数是:';
print_r($arguments);
echo '===callStatic===' . PHP_EOL;
}

$name参数是方法的名称,如$a->b(),$name的值就是"b"。$arguments是参数数组,如$a->b("1",2);则$arguments=["1", 2];

__set()和__get()

上面的__call()方法针对的是未定义的方法。而__set()和__get()则是操作不可访问的属性。注意,这里并不是指没有定义的属性,如果定义为private的属性也可以通过这两个魔术方法来进行定义,当然,也包括未定义的属性。这两个属性其实可以对应Java中对于Java Bean的属性封装。

例如$a->p=1;,两种情况:

  • 我们没有定义$p这个属性
  • 我们定义了$p,但是是private $p;

以上两种情况都适用于__set()和__get()魔术方法。

public function __set($name, $value)
{
echo '===set===' . PHP_EOL;
echo '给不可访问的属性赋值时找我' . PHP_EOL;
echo '您需要的是' . $name . ',值是:' . $value . PHP_EOL;
echo '===set===' . PHP_EOL;
if ($name == 'a') {
$this->$name = $value;
}
} public function __get($name)
{
echo '===get===' . PHP_EOL;
echo '获取不可访问的属性赋值时找我' . PHP_EOL;
echo '您需要的是' . $name . PHP_EOL;
echo '===get===' . PHP_EOL;
return $this->$name;
}

__isset()与__unset()

这两个就很好理解了,从字面意思也可以看出,一个是在使用isset()时会触发,而另一个则是在使用unset()时会触发。

需要注意的是,__isset()是在isset()和empty()时都会进行触发。都是在判断属性是否存在或者是否为空时可以进行一些操作,也是属性封装相关的操作函数。

public function __isset($name)
{
echo '===isset===' . PHP_EOL;
echo '调用isset()或empty()时来找我了' . PHP_EOL;
echo '您要找的是' . $name . PHP_EOL;
echo '===isset===' . PHP_EOL;
return property_exists($this, $name);
} public function __unset($name)
{
echo '===unset===' . PHP_EOL;
echo '调用unset()时来找我' . PHP_EOL;
echo '您要找的是' . $name . PHP_EOL;
echo '===unset===' . PHP_EOL;
}

这篇文章主要介绍的是几个非常常用的,而且在面试时出现频率也是非常高的魔术方法。在下一篇中将会介绍其它一些出现频率较低但更有意思的魔术方法。

完整代码:https://github.com/zhangyue0503/php/blob/master/newblog/PHPMagic.php

关注公众号:【硬核项目经理】获取最新文章

添加微信/QQ好友:【xiaoyuezigonggong/149844827】免费得PHP、项目管理学习资料

知乎、公众号、抖音、头条搜索【硬核项目经理】

B站ID:482780532

PHP的那些魔术方法(一)的更多相关文章

  1. PHP基础知识之魔术方法

    __construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sle ...

  2. 前端学PHP之面向对象系列第二篇——魔术方法

    × 目录 [1]构造方法 [2]析构方法 [3]不可访问属性[4]对象复制[5]字符串[6]对象不存在[7]自动加载类[8]串行化[9]函数调用 前面的话 php在面向对象部分有很多相关的魔术方法,这 ...

  3. PHP中的魔术方法(2)

    1.__get.__set这两个方法是为在类和他们的父类中没有声明的属性而设计的__get( $property ) 当调用一个未定义的属性时访问此方法__set( $property, $value ...

  4. 魔术方法__sleep 和 __wakeup

    感觉序列化和反序列化用得倒是比较少了,而json_encode和json_decode用得相对多,都是转化成串,进行入库.传输等.json更方便,但是序列化和反序列化结合这两个魔术方法使用倒还行< ...

  5. Python魔术方法-Magic Method

    介绍 在Python中,所有以"__"双下划线包起来的方法,都统称为"Magic Method",例如类的初始化方法 __init__ ,Python中所有的魔 ...

  6. php魔术方法使用场景

    php魔术方法-----__tostring(),__invoke,__call(),__callStatic ... __tostring(),__invoke() __tostring()方法是在 ...

  7. PHP中的魔术方法:__construct, __destruct , __call, __callStatic,__get, __set, __isset, __unset , __sleep, __wakeup, __toString, __set_state, __clone and __autoload

    1.__get.__set 这两个方法是为在类和他们的父类中没有声明的属性而设计的: __get( $property ) 当调用一个未定义的属性时访问此方法: __set( $property, $ ...

  8. PHP 类中的魔术方法

    定义: PHP类中以两个下画线“__”开头的方法被称为魔术方法. 分类: 例如:构造方法:__construct:析构方法:__destruct:动态重载:__set().__get().__call ...

  9. php中的魔术方法

    __construct 构造器是一个魔术方法,当对象被实例化时它会被调用.在一个类声明时它常常是第一件做的事但是没得必要他也像其他任何方法在类中任何地方都可以声明,构造器也能像其他方法样继承.如果我们 ...

  10. PHP面向对象之魔术方法复习

    魔术方法复习 2014-9-2 10:08:00 NotePad++ By jiancaigege 飞鸿影~========================= 1.__construct() 构造方法 ...

随机推荐

  1. 目录已存在导致Jenkins项目构建失败的解决方法

    Jenkins中的项目在下载源代码时,如果Working Directory中存在未加入版本控制的文件或者目录已经存在于SVN库中,会导致更新失败,整个构建终止,解决方法是将SVN的检出策略由&quo ...

  2. 用Python爬取《王者荣耀》英雄皮肤数据并可视化分析,用图说话

    大家好,我是辰哥~ 今天辰哥带大家分析一波当前热门手游<王者荣耀>英雄皮肤,比如皮肤上线时间.皮肤类型(勇者:史诗:传说等).价格. 1.获取数据 数据来源于<王者荣耀官方网站> ...

  3. NOIP 模拟 $24\; \rm matrix$

    题解 \(by\;zj\varphi\) 发现 \(\rm n,m\) 都很小,考虑分行状压. 但是上一行和下一行的按钮状态会对当前行造成影响,所以再枚举一个上一行的按钮状态. 因为对于两行,只有如下 ...

  4. WPF 中的形状和基本绘图概述

    本主题概述如何使用 Shape 对象绘图. Shape 是一种允许您在屏幕中绘制形状的 UIElement 类型. 由于它们是 UI 元素,因此 Shape 对象可以在 Panel 元素和大多数控件中 ...

  5. 14.SpringMVC之文件上传下载

    SpringMVC通过MultipartResolver(多部件解析器)对象实现对文件上传的支持. MultipartResolver是一个接口对象,需要通过它的实现类CommonsMultipart ...

  6. C# 启动 Flask for Python

    概览 最近有个需求是通过c#代码来启动 python 脚本.嘿~嘿!!! 突发奇想~~既然可以启动 python 脚本,那也能启动 flask,于是开始着手操作. 先看gif图 准备 因为使用的是.N ...

  7. Python创建二维列表的正确姿势

    Python创建二维列表的正确姿势 简介 Python中没有数组,使用list结构代替,并且list结构的功能更加强大: 支持动态扩容,无需担心元素过量 对list内的元素类型不做一致性约束 提供丰富 ...

  8. Promise.race()

    Promise.race([ ])---race竞赛,只要有一个决议了,就返回一个promise实例(对应resolve()或reject( )中参数值: 1.与Promise.all()对应的,还有 ...

  9. ubuntu 2018 apt 代理proxy设置

    永久设置 打开代理文件,好像默认没有,98proxy是自己新建的 sudo gedit /etc/apt/apt.conf.d/98proxy 在打开的文件中输入如下内容,其中username和pas ...

  10. Linux下Oracle新建用户并且将已有的数据dmp文件导入到新建的用户下的操作流程

    Oracle新建用户并且将已有的数据dmp文件导入到新建的用户下的操作流程 1.切换到oracle用户下 su - oracle 2.登录sqlplus sqlplus /nolog 3.使用sysd ...