PHP反射原理与用法深入分析
本文实例讲述了PHP反射原理与用法。分享给大家供大家参考,具体如下:
说到反射,实际上包含两个概念:
- 检视introspection判断类、方法是否存在,父子类关系,调用关系等,检视的函数文档
- 反射Reflection获取类里的方法、属性,注释等,反射类的文档
PHP官方文档写得很清晰了,下面我就说一下具体的应用。
1.参数检测
有时候需要在函数里需要判断传入的参数类型是否合法。
这时可以使用is_a、is_subclass_of来检测。或者结合反射,做更多检测。
2.动态调用
在依赖注入中,常见到这种用法,比如Laravel5.5中的Container.php
publicfunctionbuild($concrete) { //IftheconcretetypeisactuallyaClosure,wewilljustexecuteitand //handbacktheresultsofthefunctions,whichallowsfunctionstobe //usedasresolversformorefine-tunedresolutionoftheseobjects. if($concreteinstanceofClosure){ return$concrete($this,$this->getLastParameterOverride()); } $reflector=newReflectionClass($concrete); //Ifthetypeisnotinstantiable,thedeveloperisattemptingtoresolve //anabstracttypesuchasanInterfaceofAbstractClassandthereis //nobindingregisteredfortheabstractionssoweneedtobailout. if(!$reflector->isInstantiable()){ return$this->notInstantiable($concrete); } $this->buildStack[]=$concrete; $constructor=$reflector->getConstructor(); //Iftherearenoconstructors,thatmeanstherearenodependenciesthen //wecanjustresolvetheinstancesoftheobjectsrightaway,without //resolvinganyothertypesordependenciesoutofthesecontainers. if(is_null($constructor)){ array_pop($this->buildStack); returnnew$concrete; } $dependencies=$constructor->getParameters(); //Oncewehavealltheconstructor'sparameterswecancreateeachofthe //dependencyinstancesandthenusethereflectioninstancestomakea //newinstanceofthisclass,injectingthecreateddependenciesin. $instances=$this->resolveDependencies( $dependencies ); array_pop($this->buildStack); return$reflector->newInstanceArgs($instances); }
上述代码先判断是否是闭包,如果是,直接返回。不是则通过newReflectionClass($concrete);
生成反射类的实例,然后获取这个类的构造函数和参数,进行初始化的过程。
注意
反射里一个比较重要的用法invoke
当已知这个类的时候,可以通过构造ReflectionMethod来直接调用,如:
classHelloWorld{ publicfunctionsayHelloTo($name){ return'Hello'.$name; } } $reflectionMethod=newReflectionMethod('HelloWorld','sayHelloTo'); echo$reflectionMethod->invoke(newHelloWorld(),'Mike');
当不知道这个类时,知道类的对象,可以用ReflectionObject获取ReflectionMethod后调用,如:
classHelloWorld{ publicfunctionsayHelloTo($name){ return'Hello'.$name; } } $hello=newHelloWorld(); $refObj=newReflectionObject($hello); $refMethod=$refObj->getMethod('sayHelloTo'); echo$refMethod->invoke($hello,'Mike');
调用流程一般就是获取反射类ReflectionClass/反射对象ReflectionObject的实例,然后获取ReflectionMethod后,invoke。
3.获取注释,生成文档
比如PHPDoc
4.注解,增强版的注释,符合一定的规则
比如某些框架的路由,便是通过注解实现的。
5.不要为了反射而反射
PHP是一门动态语言,其实可以直接通过字符串来调用类或函数,如下:
classHelloWorld{ publicfunctionsayHelloTo($name){ return'Hello'.$name; } } $hello='HelloWorld'; $helloSay='sayHelloTo'; $helloIntance=new$hello; echo$helloIntance->$helloSay('Mike');
那么为什么还需要反射呢?
- 功能更强大
- 更安全,防止直接调用没有暴露的内部方法
- 可维护,直接写字符串是硬编码
更多关于PHP相关内容感兴趣的读者可查看本站专题:《php面向对象程序设计入门教程》、《PHP数组(Array)操作技巧大全》、《PHP基本语法入门教程》、《PHP运算与运算符用法总结》、《php字符串(string)用法总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》
希望本文所述对大家PHP程序设计有所帮助。