补个档,重新复习下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°,不存在的(°Д°)),注明出处即可!