2018年6月30日 星期六

php(ReflectionClass)(反射) 從一個實力的物件取得類別方法,並執行

ReflectionClass:
     public static string export()  //打印类的详细信息
     public string getName()        //取得类名或接口名
     public bool isInternal()       //类是否为系统内部类
     public bool isUserDefined()    //类是否为用户自定义类
     public bool isInstantiable()   //类是否被实例化过
     public bool hasMethod(string name)  //类是否有特定的方法
     public bool hasProperty(string name)//类是否有特定的属性
     public string getFileName()         //获取定义该类的文件名,包括路径名
     public int getStartLine()           //获取定义该类的开始行
     public int getEndLine()             //获取定义该类的结束行
     public string getDocComment()       //获取该类的注释
     public ReflectionMethod getConstructor()           //取得该类的构造函数信息
     public ReflectionMethod getMethod(string name)     //取得该类的某个特定的方法信息
     public ReflectionMethod[] getMethods()             //取得该类的所有的方法信息
     public ReflectionProperty getProperty(string name) //取得某个特定的属性信息
     public ReflectionProperty[] getProperties()        //取得该类的所有属性信息
     public array getConstants()                        //取得该类所有常量信息
     public mixed getConstant(string name)              //取得该类特定常量信息
     public ReflectionClass[] getInterfaces()           //取得接口类信息
     public bool isInterface()  //测试该类是否为接口
     public bool isAbstract()   //测试该类是否为抽象类
-----------------------------------------------------------------------
 class X{
    public static function go(){
        echo '<h1>go</h1>';
    }
    
    public function gogo(){
        echo '<h1>gogo</h1>';
    }
}

class Y extends X {
    
}
//==============================================================================
$y = new Y();

// 取得 static
$className = get_parent_class($y);
$ref = new ReflectionMethod($className, 'go');
$ref->invoke(NULL);
//============================================================================== 
 function make($class, $vars = array()) {
    $ref = new ReflectionClass($class);

    if(!$ref->isInstantiable()) {
        throw new Exception("类{$class} 不存在");
    }

    // 取得建構式
    $constructor = $ref->getConstructor();
    if(is_null($constructor)) {
        return new $class;
    }

    // 確定建構式的參數
    $params = $constructor->getParameters();
    
    $resolveParams = array();
    
    foreach ($params as $key=>$value) {
        $name = $value->getName();
        
        if(isset($vars[$name])) {
            $resolveParams[] = $vars[$name];
        } else {
            
            // 參數是否有默認值
            $default = $value->isDefaultValueAvailable() ? $value->getDefaultValue() : null;
            
            if(is_null($default)) {
                // 參數沒有默認值
                
                if($value->getClass()) {                    
                    
                    // 遞迴(這點似乎有點多)
                    $resolveParams[] = make($value->getClass()->getName(), $vars);
                } else {
                    throw new Exception("{$name} 没有传值且没有默认值。");
                }
            } else {
                $resolveParams[] = $default;
            }
        }
    }

    return $ref->newInstanceArgs($resolveParams);
}