在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