PHP中的魔术方法

特征

  1. __两个下划线开始
  2. 不需要显示的调用,由某些条件下触发(类似数据库中的隐式触发器)

__construct()

在对象初始化时调用,通常用来初始化成员变量,或者初始化方法

__destruct()

在对象销毁时调用,通常用来清理操作

属性的重载

定义了一个当访问不存在的属性和方法时,发生自定义的操作

__get($name)

在访问一个不存在的属性时调用,

class Device {
    public function  __get($name) {
         if(array_key_exists($name, $this->data)) {
            return $this->data[$name];
        }
        return null;
    }
}

该魔术方法最常用的地方就是通过创建一个“只读”的属性来扩展访问控制。在上面的Battery类中,有一个私有属性$charge,我们可以通过__get()魔术方法将该属性扩展为在类外部可读但不能修改。代码如下

class Battery {
    private $charge = 0;
 
    public function  __get($name) {
        if(isset($this->$name)) {
            return $this->$name;
        }
        return null;
    }
}

__set($name, $value)

__set()魔术方法在我们尝试修改一个不可访问的属性时会被调用,它接收两个参数,一个表示属性的名字,一个表示属性的值。示例代码如下:

class Device {
    public function  __set($name, $value) {
        // use the property name as the array key
        $this->data[$name] = $value;
    }
}

__isset($name)

__isset()魔术方法在对一个不可访问的属性调用isset()方法时会被调用,它接收一个参数,表示属性的名字。它应该返回一个布尔值,用来表示该属性是否存在。代码如下:

class Device {
    public function  __isset($name) {
        return array_key_exists($name, $this->data);
    }
}

__unset($name)

__unset()魔术方法在调用unset()函数销毁一个不能访问的属性时会被调用,它接收一个参数,表述属性的名字。

__toString()

__toString()在我们将对象当作字符串一样使用时会被调用,它不接收任何参数。类似java中的。toString()函数输出自定义的信息内容。

克隆对象 __clone()

默认的,对象都是按引用传值的。因此,在将一个对象赋值给另一个变量时,只是创建了指向该对象的一个引用,并没有复制该对象。为了实现真正得复制一个对象,我们需要使用clone关键字。
这种“按引用传递”的策略同样适用于包含在对象内部的对象。即使我们克隆了一个对象,在对象内部的任何对象都不会被克隆,因此最终的结果是两个对象共享了同一个内部对象。示例代码如下:

$device = new Device(new Battery(), 'iMagic');
$device2 = clone $device;
 
$device->battery->setCharge(65);
echo $device2->battery->charge;
// 65

__clone()魔术方法__clone()可以解决上面的问题。当对一个对象使用clone关键字时,该魔术方法会被调用。在这个魔术方法里,我们可以实现任何子对象的克隆,代码如下:

class Device {
    ...
    public function  __clone() {
        // copy our Battery object
        $this->battery = clone $this->battery;
    }
    ...
}

__call()

魔术方法__call()在调用不存在或不可访问的方法时会被调用。它接收两个参数,一个是调用的方法的名字,一个是包含函数参数的数组。我们可以使用这种方法调用子对象中得同名函数。

//方法不存在时报错
public function __call($name, $args)
{
    Support::Error('访问的方法不存在');
}

    原文作者:你好667
    原文地址: https://www.jianshu.com/p/cfdcc4db0fc4
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞