## 魔术方法 :__call( )实例详解 #### 1. 功能:当调用的方法不存在或权限不足时自动触发该方法。 >[info] 框架中每个类几乎都有这个魔术方法,很实用也很简单,直接上实例讲解。 #### 2. 实例: >[warning] 几乎每一步都有注释,如果感到陌生,请参阅《PHP官方手册》。 ~~~ <?php //创建父类:Member class Member{ //创建受保护属性:数组 protected $memberdata = array(); //当调用的方法不存在或权限不足时,会自动调用__call方法 public static function __call($func, $arguments){ //explode():用'_'字符串分割为数组 //list():将数组元素转为对应的独立变量:$type,$name list($type, $name) = explode('_', $func); //如何$type字符串不在数组'set'和'get'中任何一个 //或者$name为空的话,则调用的方法名称不正确,直接返回'空'; if(!in_array($type, array('set','get')) || $name==''){ return ''; } //获取调用当前方法的类名 //即:当前方法静态绑定的类名: 如 User $feature = get_called_class(); //判断$type值 switch($type){ //如果$type = 'set',则是给属性$memeberdata赋值 case 'set': //将当前方法的参数数组的值$arguments[0] //赋给属性 $memberdata[$feature][$name]:注意是二维数组 //当前方法只有一个值:$arguments[0] self::$memberdata[$feature][$name] = $arguments[0]; break; //如果$type = 'get',则是获取属性$memeberdata的值 case 'get': //如果 self::$memberdata[$feature][$name]存在则返回该值,否则返回:空 return isset(self::$memberdata[$feature][$name])? self::$memberdata[$feature][$name] : ''; break; default: } } } //创建子类:User,继承自:Member类 class User extends Member{ //定义公共方法:show(),用来输出数据 public function show(){ //获取调用当前方法的类名,如:User $feature = get_called_class(); //如果self::$memberdata[$feature]属性存在 if(self::$memberdata[$feature]){ //输出与当前类所对应的$memberdata[$feature]属性值 foreach(self::$memberdata[$feature] as $key=>$member){ echo $key.':'.$member.'<br>'; } } } } //创建子类:Profession,继承自:Member类 class Profession extends Member{ //定义公共方法:show(),用来输出数据 public function show(){ //获取调用当前方法的类名,如:Profession $feature = get_called_class(); //如果self::$memberdata[$feature]属性存在 if(self::$memberdata[$feature]){ //输出与当前类所对应的$memberdata[$feature]属性值 foreach(self::$memberdata[$feature] as $key=>$member){ echo $key.':'.$member.'<br>'; } } } } //调用set_name(),set_age() //当前类User和父类中都没有set_name方法,于是自动触发父类__call()方法 //父类Member中的__call($func,$arguments)是系统魔术方法 //在__call方法中,方法名set_name转换为变量$type和$name //并根据$type,完成属性的动态赋值或读取操作 //set_name(),set_age()分别完成了对$memberdata[$feature]属性的动态赋值操作 $user = new User(); $user -> set_name('ThinkPHP'); $user -> set_age(10); $user -> show(); //调用set_profession(),set_price() //当前类User和父类中都没有set_name静态方法,于是自动触发父类__callStatic()方法 //父类Member中的__callStatic($func,$arguments)是系统魔术方法 //在__callStatic方法中,方法名set_name转换为变量$type和$name //并根据$type,完成属性的动态赋值或读取操作 //set_name(),set_age()分别完成了对$memberdata[$feature]属性的动态赋值操作 $profession = new Profession(); $profession -> set_lession('模型'); $profession -> set_teacher('理达课堂'); $profession -> show(); ~~~ * 运行结果: ~~~ name:ThinkPHP age:10 lession:模型 teacher:理达课堂 ~~~ #### 4. 总结: >[success] 当调用不存在的方法,或者越权调用某个方法,__call( )方法提供了一种容错机制,可以让我们更加灵活的使用面向对象编程,带来的好处。