「php化整为零系列」三、Magic(魔术方法)

2016-08-02  本文已影响68人  Bill_Wang
源码地址:https://github.com/wilfordw/phpTutorial

该系列我只写我的理解,非官方解释,如不够专业请见谅

PHP有很多魔术方法,比如__autoload就是一个。这里主要介绍的是__invoke__call__callStatic 这3个方法

invoke

PHP5.3新增了一个叫做__invoke的魔术方法,这样在创建实例后,可以直接调用对象

<?php

class A
 {
    public function __invoke($str)
    {
        print "A::__invoke(): {$str}";
    }
 }
$a = new A;
$a("Hello World");//输出'HelloWorld'

call&&callStatic

php 5.3 后新增了 __call__callStatic魔法方法。
__call 当要调用的方法不存在或权限不足时,会自动调用__call 方法。
__callStatic 当调用的静态方法不存在或权限不足时,会自动调用__callStatic方法。

<?php

class Member{

    protected $memberdata = array();

    public function __call($func, $arguments){
        list($type, $name) = explode('_', $func);
    
        if(!in_array($type, array('set','get')) || $name==''){
            return '';
        }

        switch($type){
            case 'set':
                $this->memberdata[$name] = $arguments[0];
                break;
            
            case 'get':
                return isset($this->memberdata[$name])? $this->memberdata[$name] : '';
                break;
            
            default:
        }

    }

}


class User extends Member{

    public function show(){
        if($this->memberdata){
            foreach($this->memberdata as $key=>$member){
                echo $key.':'.$member.'<br>';
            }
        }
    }

}


class Profession extends Member{

    public function show(){
        if($this->memberdata){
            foreach($this->memberdata as $key=>$member){
                echo $key.':'.$member.'<br>';
            }
        }
    }

}

$userobj = new User();
$userobj->set_name('fdipzone');
$userobj->set_age(29);
$userobj->show();

$probj = new Profession();
$probj->set_profession('IT SERVICE');
$probj->set_price(2500);
$probj->show();

/*输出
name:fdipzone
age:29
profession:IT SERVICE
price:2500*/
?>

利用__call方法实现了扩展性极大的setter/getter

<?php

class Member{

    protected static $memberdata = array();

    public static function __callStatic($func, $arguments){

        list($type, $name) = explode('_', $func);
        
        if(!in_array($type, array('set','get')) || $name==''){
            return '';
        }

        $feature = get_called_class();

        switch($type){
            case 'set':
                self::$memberdata[$feature][$name] = $arguments[0];
                break;

            case 'get':
                return isset(self::$memberdata[$feature][$name])? self::$memberdata[$feature][$name] : '';
                break;

            default:
        }
    
    }

}


class User extends Member{

    public static function show(){

        $feature = get_called_class();

        if(self::$memberdata[$feature]){
            foreach(self::$memberdata[$feature] as $key=>$member){
                echo $key.':'.$member.'<br>';
            }
        }
    }

}


class Profession extends Member{

    public static function show(){

        $feature = get_called_class();

        if(self::$memberdata[$feature]){
            foreach(self::$memberdata[$feature] as $key=>$member){
                echo $key.':'.$member.'<br>';
            }
        }
    }

}

User::set_name('fdipzone');
User::set_age(29);
User::show();

Profession::set_profession('IT SERVICE');
Profession::set_price(2500);
Profession::show();

?>

__call __callStatic只是静态方法的实现版本,值得注意的是get_called_class()方法是获取子类的类名。
静态方法中要用self::调用方法和变量,在实例对象中要用$this->

上一篇 下一篇

猜你喜欢

热点阅读