PHP反射机制PHP反射机制从PHP5开始支持。如果你做业务开发,你应该很少接触反射。其实我和它接触不多。最近在学习laravel的“优雅”时,接触到了它的反射用法,这是我自己的看法。反思按照之前的套路,我们来看看官方手册,官方是怎么说的。ReflectionPHP5具有完整的反射API,增加了对类、接口、函数、方法和扩展进行逆向工程的能力。此外,ReflectionAPI提供了从函数、类和方法中提取文档注释的方法。我的理解是php的反射机制可以获取到类中的属性方法,private和protected的也可以使用。以上是官方文档给出的东西。老实说,我看完后并没有太大的感觉。可以得到的点是我们可以通过这个窥探一个类的所有信息,就像在别人的窗户上开了一个洞一样。应该怎么使用,或者说应该基于什么场景使用?还是疼。laravel中的反思laravel整个框架设计的“优雅”在于容器、IOC和依赖注入。我们来看一下容器中一段关于反射的代码:IlluminateContainerContainer:/***实例化给定类型的具体实例。**@paramstring$concrete*@paramarray$parameters*@returnmixed**@throws\Illuminate\Contracts\Container\BindingResolutionException*/publicfunctionbuild($concrete,array$parameters=[]){//如果具体类型实际上是一个闭包,我们将只执行它并//交回函数的结果,这允许函数//用作解析器,以便对这些对象进行更精细的解析。if($concreteinstanceofClosure){return$concrete($this,$parameters);}}$reflector=newReflectionClass($concrete);//如果类型不可实例化,则开发人员正在尝试解析//抽象类型,例如抽象类的接口,并且//没有为抽象注册绑定,所以我们需要纾困。if(!$reflector->isInstantiable()){if(!empty($this->buildStack)){$previous=implode(',',$this->buildStack);$message="目标[$concrete]在构建[$previous]时不可实例化。";}else{$message="目标[$concrete]不可实例化。";}抛出新的BindingResolutionException($message);}$this->buildStack[]=$concrete;$constructor=$reflector->getConstructor();//如果没有构造函数,则意味着没有依赖关系//我们可以立即解析对象的实例,而无需//从这些容器中解析任何其他类型或依赖关系。如果(is_null($constructor)){array_pop($this->buildStack);返回新的$混凝土;}$dependencies=$constructor->getParameters();//一旦我们拥有了所有构造函数的参数,我们就可以创建每个//依赖实例,然后使用反射实例来生成//这个类的新实例,将创建的依赖注入。$parameters=$this->keyParametersByArgument($dependencies,$parameters);$instances=$this->getDependencies($dependencies,$parameters);array_pop($this->buildStack);返回$reflector->newInstanceArgs($instances);}是实现绑定Class方法,build方法下面分析一下:Parameter:$concreatestring类似于Model::class,不难理解。$parameters数组参数不难理解。判断$concreate是否为匿名类(闭包),如果是匿名类则执行该函数。创建一个反射类来映射这个类。判断这个类是否可以被实例化,也就是看构造函数是否是私有的。否则,抛出异常。数组在容器成员变量中维护这个类,反射实例调用构造函数获取返回值。判断返回值是否为空。如果为空,说明不需要参数依赖,直接实例化。否则,获取构造函数的参数依赖关系,并将传入参数与依赖参数进行比较。最后调用newInstanceArgs实例化,然后返回实例。后记其实上面laravel中的例子已经很好的阐明了反射机制的使用。可能你现在的业务场景可能用不上这个机制。但是,当你遇到它时,请记住,也可以使用这种方法。当你需要实例化一个类,但是这个类是完全封闭的或者你不知道的时候,你可以创建反射来映射这个类,通过一系列的检测最终实例化这个类,尤其是在动态运行中。基于这个机制,其实可以玩出很多花样。例如,自动生成文档的能力。实现MVC的架构,使用反射自动调用$class=newReflectionClass(ucfirst($controller));$controller=$class->newInstance();如果($class->hasMethod($method)){$method=$class->getMethod($method);$method->invokeArgs($controller,$arguments);}else{thrownewException("{$controller}控制器方法{$method}不存在!");}执行单元测试$class=newReflectionClass($class);如果($class->hasMethod($method)){$method=$class->getMethod($method);$object=$class->newInstance();$class=$method->invokeArgs(new$object,$params);var_dump($res===$assert);laravel中的反射帮助它解决了DI容器的依赖注入问题。还有很多有趣的事情等着你去尝试。这个机制能玩出多少花样就看你怎么玩了。
