补个档,重新复习下php的几种魔术方法,同时魔术方法也是必须掌握的,面试什么的也是必考的.附上php文档的相关警告:PHP 将所有以两个下划线开头的类方法保留为魔术方法。所以在定义类方法时,除了讲到的魔术方法,建议不要以两个下划线为前缀. 切记切记~~
常用魔术方法
__construct()
1 2 3 4 5 6 7 8
| class A { function __construct() //参数列表可选 { } } $instance = new A();
|
__destruct()
- 描述:析构函数,在对象的所有引用被删除或者脚本执行结束时调用
1 2 3 4 5 6 7 8 9 10
| class A { function __destruct() //参数列表为空 { } } $instance = new A(); unset($instance);
|
__toString()
- 描述:当类被当作字符串时,此方法返回字符串。返回值为string,无参数。
1 2 3 4 5 6 7 8 9 10 11 12
| class A{ function __toString() { return "I AM A"; } } $instance = new A(); echo $instance; print $instance;
|
__get()
- 描述:当读取不可访问属性的调用,参数string值,返回值mixed
1 2 3 4 5 6 7 8 9 10 11 12 13
| class A{ private $a = 1; function __get($name) //$name为要访问的属性名 { if(isset($this->$name)){ return $this->$name; } } } $instance = new A(); echo $instance->a;
|
__set()
- 描述:当给不可访问的属性赋值时调用,参数1(属性名) string 参数2(赋值) mixed ,返回值为void
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class A{ private $a = 1; function __set($name,$value) { if(isset($this->$name)){ $this->$name=$value; } } function __get($name){ if(isset($this->$name)){ return $this->$name; } } } $instance = new A(); $instance->a = 3; echo $instance->a;
|
__isset()
- 描述:对当不可访问的属性调用isset()或empty()时,__isset()会被自动调用,接受一个string 参数(被访问的属性名)
1 2 3 4 5 6 7 8 9 10 11
| class A{ private $a; function __isset($name) //被访问的属性名 { echo $name."__isset is invoked"; } } $instance = new A(); isset($instance->a);
|
__unset()
- 描述:对当不可访问的属性调用unset()时,__unset()会被自动调用,接受一个string 参数(被访问的属性名)
1 2 3 4 5 6 7 8 9 10 11
| class A{ private $a; function __unset($name) //被访问的属性名 { echo $name."__unset is invoked"; } } $instance = new A(); unset($instance->a);
|
__call()
- 描述:当对象调用一个不可访问的方法是,__call()会被自动调用,接受两个参数,第一个参数string(方法名),第二个参数array(参数列表)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class A{ private function inside($a,$b) { echo $a.'_'.$b; } function __call($name,$args) //方法名&参数列表 { echo 'funciton_name:'.$name.' parameter:'.implode(' , ',$args); } } $instance = new A(); $instance->inside(1,2,3);
|
__callStatic()
- 描述:当对象调用一个不可访问的静态方法是,__callStatic()会被自动调用,接受两个参数,第一个参数string(方法名),第二个参数array(参数列表),修饰必须是可见的以及静态的
1 2 3 4 5 6 7 8 9 10 11 12 13
| class A{ private static function inside($a,$b) { echo $a.'_'.$b; } public static function __callStatic($name,$args) //修饰必须是可见的以及静态的 { echo 'static_funciton_name:'.$name.' parameter:'.implode(' , ',$args); } } A::inside(1,2,3);
|
__clone()
- 描述:当使用关键字clone对象是,__clone()方法会被自动调用.
- 作用:因为clone是浅克隆,当要复制的对象内部有一个引用属性时,并不会进行复制,而是照搬引用,所以此时需要在__clone方法中对某些引用属性进行深克隆
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| class A{ public $obj ; public function __construct(B $ojb) { $this->obj = $ojb; } function __clone(){ $this->obj = clone $this->obj; } } class B{ public $content="abc"; } $a = new A(new B()); $b = clone $a; $a->obj->content = "efg"; echo $b->obj->content;
|
__sleep()
- 描述:serialize() 函数会检查类中是否存在一个魔术方法 __sleep()。如果存在,该方法会先被调用,然后才执行序列化操作。此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称的数组。如果该方法未返回任何内容,则 NULL 被序列化,并产生一个 E_NOTICE 级别的错误。
- 备注:__sleep() 不能返回父类的私有成员的名字。这样做会产生一个 E_NOTICE 级别的错误。可以用 Serializable 接口来替代。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class A{ public $var1 = 1; public $var2 = 2; public $var3 = 3; public function __sleep() //返回应被序列化的变量名称的数组 { return array('var1','var2'); } } $instance = new A(); echo serialize($instance);
|
Notice:serialize()和unserialize(),是将php的值与字符串相互转化的方法(序列化与反序列化),主要便于存储,同时也不丢失类型结构。
__wakeup()
- 描述:unserialize(反序列化)对象时,__wakeup()会被自动调用。
- 作用:经常用在反序列化操作(字符串还原成对象时)中,例如重新建立数据库连接,或执行其它初始化操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| class A{ public $var1 = 1; public $var2 = 2; public $var3 = 3; public function __sleep() { return array('var1','var2'); } function __wakeup() { $this->var1 = 233; } } $instance = new A(); $a=serialize($instance); echo $a; $a=unserialize($a); echo $a->var1;
|
魔术方法实现重载
属性重载
PHP所提供的”属性重载”是指动态地”创建”类属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| class A{ private $data = array(); public $declared = 1; private $hidden = 2; public function __set($name , $value) { $this->data[$name] = $value; } public function getData() { return $this->data; } } $instance = new A(); $instance->a = 3; print_r($instance->getData());
|
方法重载
传统的”重载”是用于提供多个同名的类方法,但各方法的参数类型和个数不同。不过要实现相同的功能可以使用__call()魔术方法.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| class A{ function __call($name,$args) { if($name == 'func') { $args_num = count($args); $invoke_name=$name.$args_num; if(method_exists($this,$invoke_name)){ call_user_func_array(array($this,$invoke_name),$args); } } } function func1($arg1) { echo "invoke func1:".$arg1; } function func2($arg1,$arg2) { echo "invoke func2:".$arg1.','.$arg2; } } $instance = new A(); $instance->func(1); $instance->func(1,2);
|
notice:call_user_func_array方法的第一个参数是callable类型,一个已实例化的 object 的方法被作为 array 传递,下标 0 包含该 object,下标 1 包含方法名。 在同一个类里可以访问 protected 和 private 方法。
参考资料
PHP官方文档
最后更新时间:
对本文内容有任何意见,建议,疑问etc,均可通过邮箱联系我,逗比博主尽最大努力回复O(∩_∩)O,如需转载(tan90°,不存在的(°Д°)),注明出处即可!