您好,欢迎访问一九零五行业门户网

php魔术方法属性重载方法 - 南十字

php有一类很神奇的方法,这些方法是保留方法,通常不会在外部被显式调用,他们使用双下划线(__)开头,他们被称为魔术方法(magic methods)。php官方也不建议定义其他双下划线开头的方法。
这次介绍属性重载方法:get/set/isset/unset
public void __set ( string $name , mixed $value )public mixed __get ( string $name )public bool __isset ( string $name )public void __unset ( string $name )
这些方法触发的时机,都是在访问不可访问的属性的时候。
如以下:
1 php 2 3 class cls{ 4 5 private $a = 0; 6 protected $b = 1; 7 public $c = 2; 8 var $d = 3; 9 10 private $_properties = array(0);11 12 public function __set($name, $value){13 echo __method__ . ' is called! ' . json_encode(func_get_args()) . \n;14 return $this->_properties[$name] = $value;15 }16 17 public function __get($name){18 echo __method__ . ' is called! ' . json_encode(func_get_args()) . \n;19 return $this->_properties[$name];20 }21 22 public function __isset($name){23 echo __method__ . ' is called! ' . json_encode(func_get_args()) . \n;24 return isset($this->_properties[$name]);25 }26 27 public function __unset($name){28 echo __method__ . ' is called! ' . json_encode(func_get_args()) . \n;29 unset($this->_properties[$name]);30 }31 32 public function dump(){33 echo ====================== dump start ====================\n;34 echo str35 a: $this->a36 b: $this->b37 c: $this->c38 d: $this->d\n39 str;40 foreach($this->_properties as $k => $v){41 echo str42 property $k: $v\n43 str;44 }45 46 echo ====================== dump stop =====================\n;47 48 }49 }50 $string = 'abcdef';51 $obj = new cls();52 53 $list = array('isset', 'get', 'set', 'isset', 'unset', 'isset');54 $obj->dump();55 foreach($list as $method){56 for($i = 0 ; $i strlen($string) ; $i ++){57 $char = $string{$i};58 echo ------ $method : $char ------\n;59 switch($method){60 case 'isset':61 echo json_encode($tmp = isset($obj->$char)) . \n;62 break;63 case 'get':64 echo json_encode($tmp = $obj->$char) . \n;65 break;66 case 'set':67 echo json_encode($tmp = $obj->$char = $char . -val) . \n;68 break;69 case 'unset':70 unset($obj->$char);71 break;72 default:73 break;74 }75 }76 $obj->dump();77 }
结果输出:
====================== dump start ==================== a: 0 b: 1 c: 2 d: 3 property 0: 0====================== dump stop =====================------ isset : a ------cls::__isset is called! [a]false------ isset : b ------cls::__isset is called! [b]false------ isset : c ------true------ isset : d ------true------ isset : e ------cls::__isset is called! [e]false------ isset : f ------cls::__isset is called! [f]false====================== dump start ==================== a: 0 b: 1 c: 2 d: 3 property 0: 0====================== dump stop =====================------ get : a ------cls::__get is called! [a]null------ get : b ------cls::__get is called! [b]null------ get : c ------2------ get : d ------3------ get : e ------cls::__get is called! [e]null------ get : f ------cls::__get is called! [f]null====================== dump start ==================== a: 0 b: 1 c: 2 d: 3 property 0: 0====================== dump stop =====================------ set : a ------cls::__set is called! [a,a-val]a-val------ set : b ------cls::__set is called! [b,b-val]b-val------ set : c ------c-val------ set : d ------d-val------ set : e ------cls::__set is called! [e,e-val]e-val------ set : f ------cls::__set is called! [f,f-val]f-val====================== dump start ==================== a: 0 b: 1 c: c-val d: d-val property 0: 0 property a: a-val property b: b-val property e: e-val property f: f-val====================== dump stop =====================------ isset : a ------cls::__isset is called! [a]true------ isset : b ------cls::__isset is called! [b]true------ isset : c ------true------ isset : d ------true------ isset : e ------cls::__isset is called! [e]true------ isset : f ------cls::__isset is called! [f]true====================== dump start ==================== a: 0 b: 1 c: c-val d: d-val property 0: 0 property a: a-val property b: b-val property e: e-val property f: f-val====================== dump stop =====================------ unset : a ------cls::__unset is called! [a]------ unset : b ------cls::__unset is called! [b]------ unset : c ------------ unset : d ------------ unset : e ------cls::__unset is called! [e]------ unset : f ------cls::__unset is called! [f]====================== dump start ====================cls::__get is called! [c]cls::__get is called! [d] a: 0 b: 1 c: d: property 0: 0====================== dump stop =====================------ isset : a ------cls::__isset is called! [a]false------ isset : b ------cls::__isset is called! [b]false------ isset : c ------cls::__isset is called! [c]false------ isset : d ------cls::__isset is called! [d]false------ isset : e ------cls::__isset is called! [e]false------ isset : f ------cls::__isset is called! [f]false====================== dump start ====================cls::__get is called! [c]cls::__get is called! [d] a: 0 b: 1 c: d: property 0: 0====================== dump stop =====================
特别强调,当这个属性不存在(基于当前访问权限)的时候,才会触发这些方法。因此严重建议使用确定的键值进行get/set处理,特别是对应的键值不要有访问权限问题,如上例中的a和b,会导致在类内部、类外部、子类内处理的方式不同,开发时产生不可预知的返回值,极易产生bug。
empty方法不能调用属性重载方法。
$tmp = $obj->$char = $char . -val
此例中,__set自身的返回值将被忽略,同样__get也不会被调用。
此外:属性重载方法必须声明为public,同时参数不能使用引用传递,静态属性不能通过这些方法重载,这些方法也不能被声明为static。
当然,使用魔术方法的时候,也会对反射系统造成影响。
其它类似信息

推荐信息