- PHP中的魔术方法,指的一般是:以双下划线开头,不需要显示的调用,在特定的条件下,会被自动调用的方法。
- 这里记录了目前为止所有的 魔术方法,一共15个
- 这些魔术方法,几乎都是为了类的实例服务的,这么规定给我们留下了很大的操作空间
- 由于会被自动调用,所以规定的访问权限一般都是 public
- 针对于 属性
- __get():访问不可访问的属性会被自动调用
- __set():设置不可设置的属性会被自动调用
- __isset():试图通过 empty()、isset() 来访问不可访问的属性时会被自动调用
- __unset() :试图在外部通过unset()方法,来删除对象的某一个属性时会被自动调用
- 序列化和反序列化
- __sleep():序列化自动调用
- __wakeup():反序列化自动调用
- 构造和析构
- __construct():创建对象自动调用
- __destruct():销毁对象时自动调用
- 调试输出对象
- __set_state():var_export() 时自动调用
- __debuginfo():var_dump() 时自动调用
- 打印对象
- __toString():将对象当字符串使用时自动调用
- 克隆对象
- __clone():克隆对象时自动调用
- 访问方法
- __call():访问无法访问的非静态方法是自动调用
- __callStatic():访问无法访问的静态方法时调用
- 将对象当成方法时调用
- __invoke():就这个方法不像是其它方法一样成对出现
PHP中所有的魔术方法
1. __construct()
创建对象时调用。构造方法,创建一个类实例自动调用它的构造函数来完成创建,PHP中的构造函数逼向Java不是类名,而是 __construct().
<?phpclass Person{private $name;private $gender;private $age;public function __construct($name, $gender, $age){$this->name = $name;$this->gender = $gender;$this->age = $age;}}var_dump(new Person('xs', 'male', 24));/*object(Person)#1 (3) {["name":"Person":private]=>string(2) "xs"["gender":"Person":private]=>string(4) "male"["age":"Person":private]=>int(24)}*/
2. __destruct()
销毁对象时被自动调用,一般来说,我们并不用去特别设置这个函数。
<?phpclass Person{private $name;private $gender;private $age;public function __construct($name, $gender, $age){$this->name = $name;$this->gender = $gender;$this->age = $age;}public function __destruct(){print '对象被销毁了!';}}$p1 = new Person('xs', 'male', 24);unset($p1); // 对象被销毁了!
3. __call()
当访问不存在的非静态方法时被自动调用,这个方法接受两个参数,第一个参数是方法的名称,第二参数是一个数组用于保存形参
<?phpclass Person{private $name;private $gender;private $age;public function __construct($name, $gender, $age){$this->name = $name;$this->gender = $gender;$this->age = $age;}public function __call($name, $arguments){echo '__call is called ' . "\r";echo 'Method Name :' . $name . "\r" . 'Args :' . implode(',', $arguments);}public static function __callStatic($name, $arguments){echo '__callStatic is called ' . "\r";echo 'Method Name :' . $name . "\r" . 'Args :' . implode(',', $arguments);}}$p1 = new Person('xs', 'male', 24);$p1->go(1, 2, 3, 4);/*__call is calledMethod Name :goArgs :1,2,3,4*/
4. __callStatic()
和__call()类似,当访问不存在静态的方法时会被自动调用
<?phpclass Person{private $name;private $gender;private $age;public function __construct($name, $gender, $age){$this->name = $name;$this->gender = $gender;$this->age = $age;}public function __call($name, $arguments){echo '__call is called ' . "\r";echo 'Method Name :' . $name . "\r" . 'Args :' . implode(',', $arguments);}public static function __callStatic($name, $arguments){echo '__callStatic is called ' . "\r";echo 'Method Name :' . $name . "\r" . 'Args :' . implode(',', $arguments);}}$p1 = new Person('xs', 'male', 24);$p1::go(1, 2, 3, 4);/*__callStatic is calledMethod Name :goArgs :1,2,3,4*/
5. __get()
当试图访问获取不到的属性时,会被自动调用,这个方法只有一个参数这个参数是访问的属性名称。
<?phpclass Person{private $name;private $gender;private $age;public function __construct($name, $gender, $age){$this->name = $name;$this->gender = $gender;$this->age = $age;}public function __get($name){echo '访问的属性无法直接获取' . " $name \r";}}$p1 = new Person('xs', 'male', 24);// 1. 比如这里我们访问一个私有的属性$p1->age; // 访问的属性无法直接获取 age// 2. 访问一个不存在的属性$p1->go; // 访问的属性无法直接获取 go
6. __set()
当设置私有的属性或者是其他不存在的属性,总之设置当前无法设置的属性时该方法会被自动调用。接收两个参数,第一个参数是被设置的属性,第二个参数是被设置属性的值。
<?phpclass Person{private $name;private $gender;private $age;public function __construct($name, $gender, $age){$this->name = $name;$this->gender = $gender;$this->age = $age;}public function __set($name, $value){echo "无法设置 $name 为 $value \r";}}$p1 = new Person('xs', 'male', 24);$p1->age = 10; // 无法设置 age 为 10$p1->go = 10; // 无法设置 go 为 10
7. __isset()
当试图通过 isset() 或者 empty() 来访问不可访问的属性时调用该方法
<?phpclass Person{private $name;private $gender;private $age;public function __construct($name, $gender, $age){$this->name = $name;$this->gender = $gender;$this->age = $age;}public function __isset($name){echo "无法通过isset($name) 或者 empty($name) 访问属性$name \r";}}$p1 = new Person('xs', 'male', 24);isset($p1->age); // 无法通过isset(age) 或者 empty(age) 访问属性ageempty($p1->age); // 无法通过isset(age) 或者 empty(age) 访问属性age
8. __unset()
在对象里面加上了”unset()”这个方法之后,在对象外部使用”unset()”函数删除对象内部的私有成员属性时,自动调用”unset()”函数来帮我们删除对象内部的私有成员属性,这个方法也可以在类的内部定义成私有的。在对象里面加上下面的代码就可以了:
<?phpclass Person{private $name;private $gender;private $age;public function __construct($name, $gender, $age){$this->name = $name;$this->gender = $gender;$this->age = $age;}private function __unset($name){echo "调用了 unset($name) 删除一个类属性 \r";unset($this->$name);}}// 删除某个实例的属性$p1 = new Person('xs', 'male', 24);unset($p1->age);var_dump($p1);/*调用了 unset(age) 删除一个类属性object(Person)#1 (2) {["name":"Person":private]=>string(2) "xs"["gender":"Person":private]=>string(4) "male"}*/
9. __sleep()
在类外部使用serialize()时自动调用
<?phpclass Person{private $name;private $gender;private $age;public function __construct($name, $gender, $age){$this->name = $name;$this->gender = $gender;$this->age = $age;}public function __sleep(){echo "当在类外部使用serialize()时会调用这里的__sleep()方法 \r";$this->name = base64_encode($this->name);$this->gender = base64_encode($this->gender);$this->age = base64_encode($this->age);// 这里必须返回一个数值,里边的元素表示返回的属性名称return array('name', 'gender', 'age');}}$person = new Person('向上', '男', 24); // 初始赋值$ser = serialize($person);echo $ser; // O:6:"Person":3:{s:12:"
10. __wakeup()
反序列化的时候调用
<?php// ... ....
11. __toString()
直接输出对象引用时自动调用的方法,简单来说就是,对象被当成字符串使用的使用。我们都知道,PHP中是不可以直接 echo $instance,如果我们自己定义并按照个人的需求去类中添加 “__toString()”,就可以了。
<?phpclass Person{private $name;private $gender;private $age;public function __construct($name, $gender, $age){$this->name = $name;$this->gender = $gender;$this->age = $age;}public function __toString(){return'name :' . $this->name . '\r' .'gender :' . $this->gender . '\r' .'age :' . $this->age ;}}echo (new Person('xs', 'male', 24)); // name :xs\rgender :male\rage :24
12. __invoke()
当对象被当成函数去使用的时候会被自动调用
<?phpclass Person{private $name;private $gender;private $age;public function __construct($name, $gender, $age){$this->name = $name;$this->gender = $gender;$this->age = $age;}public function __invoke(){echo '__invoked() is called';}}$p1 = new Person('xs', 'male', 24);$p1(); // __invoked() is called
13. __set_state()
当调用 var_export() 导出类时,此静态方法会被自动调用. 就是var_export()的回调函数
先不添加这个方法,我们使用 var_export**
<?phpclass Person{private $name;private $gender;private $age;public function __construct($name, $gender, $age){$this->name = $name;$this->gender = $gender;$this->age = $age;}}var_export(new Person('向上', '男', 24));/*Person::__set_state(array('name' => '向上','gender' => '男','age' => 24,))*/
添加这个方法
14. __clone()
克隆对象时被自动调用
<?phpclass Person{private $name;private $gender;private $age;public function __construct($name, $gender, $age){$this->name = $name;$this->gender = $gender;$this->age = $age;}public function __clone(){echo 'who clone me';}}$p1 = new Person('xs', 'male', 24);$p2 = clone $p1; // who clone me
15. __debuglnfo()
该方法在var_dump()类对象的时候被调用,如果没有定义该方法,则var_dump会打印出所有的类属性,5.6以上的版本
<?phpclass Person{public $name;public $gender;public $age;public function __construct($name, $gender, $age){$this->name = $name;$this->gender = $gender;$this->age = $age;}public function __debugInfo(){return ['name' => $this->name,'age' => $this->age,'gender' => $this->gender];}}var_dump(new Person('xs', '男', 24));
