PHP中反射类ReflectorClass的运用

LAMP 17codes 189℃ 0评论

最近研读Laravel框架的源码,脑补了一下php中的反射类ReflectorClass。

php官方文档给出的定义:PHP 5 具有完整的反射 API,添加了对类、接口、函数、方法和扩展进行反向工程的能力。 此外,反射 API 提供了方法来取出函数、类和方法中的文档注释。

class Person{
    protected  $name;
    protected $age;
    protected  $sex;

    public function __construct($name,$age,$sex)
    {
        $this->name=$name;
        $this->age=$age;
        $this->sex=$sex;
    }
    public function showInfo()
    {
        echo '姓名:'.$this->name,' 年龄:'.$this->age,' 性别:'.$this->sex;
    }
}

现在通过反射创建Person的实例化对象;

function getInstance($className,$paramaters=[]){
    //创建反射类
    $reflector=new ReflectionClass($className);
    //如果可以实例化,
    if($reflector->isInstantiable()){
        $constructor=$reflector->getConstructor();
        if(is_null($constructor)){
            //如果构造函数为空
            //return new  $className();
            //或者
            return $reflector->newInstance();
        }
        //通过参数实例化对象
        return $reflector->newInstanceArgs($paramaters);
    }else{
        throw new ReflectionException('不能实例化');
    }
}
$ins=getInstance($className,array('jack','17','男'));
$ins->showInfo();

这样一个简单的通过反射类获取对象就完成了。那么通过反射类还可以获取更多的类的信息

  • 获取类的属性
$properties =$reflector->getProperties();//获取所有属性
//遍历属性
foreach($properties as $property){
    echo $property->getName()."\n";//获取属性名
}

getProperties()方法默认情况下是获取所有的属性,如果只想获取public、protected或private属性,可以指定参数getProperties(ReflectionProperty::IS_PRIVATE)

参数列表: ReflectionProperty::IS_STATIC
ReflectionProperty::IS_PUBLIC
ReflectionProperty::IS_PROTECTED
ReflectionProperty::IS_PRIVATE

如果需要同时获取多个可以传递多个参数,参数之间通过逻辑或分割,例如:ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PROTECTED

  • 获取类的方法,可以查看php官方给出的资料
$showInfo=$reflector->getMethod('showInfo');//获取方法
$showInfo->invoke($reflector->newInstanceArgs($paramaters));//执行
  • 获取构造函数
$constructor=$reflector->getConstructor();//获取构造函数

值得一提的是,在Laravel中,解析反射类的构造函数参数这部分,在IOC依赖反转容器的实现部分通过反射来实现自动绑定,如下代码、代码部分去掉一些其他相关的,加上了一些中文注释

public function build($concrete, array $parameters = [])
{
    //如果闭包函数,匿名类直接执行
    if ($concrete instanceof Closure) {
        return $concrete($this, $parameters);
    }
    //创建反射类
    $reflector = new ReflectionClass($concrete);
    if (! $reflector->isInstantiable()) {//判断可以实例化,
        if (! empty($this->buildStack)) {
            $message = "Target [$concrete] is not instantiable while building [$previous].";
        } else {
            $message = "Target [$concrete] is not instantiable.";
        }
        throw new BindingResolutionException($message);
    }
    $constructor = $reflector->getConstructor();//获取构造函数
    if (is_null($constructor)) {//如果构造函数为空,可以直接创建对象并且返回
        return new $concrete;
    }

    $dependencies = $constructor->getParameters();//构造函数不为空的时候,需要分析构造函数的参数列表
    $parameters = $this->keyParametersByArgument(//将参数的数组,从索引数组转换成关联数组
        $dependencies, $parameters
    );
     /*  getDependencies 此方法是对参数列表递归解析,当前可以省略,后面再做解释  */
    $instances = $this->getDependencies(
        $dependencies, $parameters
    );
    //
    return $reflector->newInstanceArgs($instances);
}

Laravel中实现容器的重要部分,就是通过反射类ReflectorClass实现的。还有诸如插件hook都可以实现,有时间再写一篇hook插件来分享…..

作者:一起代码网
原文链接:http://www.17codes.com/archives/124
欢迎转载,但请保留作者和本文链接,谢谢!
欢迎在下面的评论区与我交流。

转载请注明:一起代码 » PHP中反射类ReflectorClass的运用

喜欢 (0)
发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址