PHP反射实际应用示例
本文实例讲述了PHP反射实际应用。分享给大家供大家参考,具体如下:
1.自动生成文档
根据反射的分析类,接口,函数和方法的内部结构,方法和函数的参数,以及类的属性和方法,可以自动生成文档。
id; } publicfunctionsetId($id=1) { $this->id=$id; } } $ref=newReflectionClass('Student'); $doc=$ref->getDocComment(); echo$ref->getName().':'.getComment($ref),"
"; echo"属性列表:
"; printf("%-15s%-10s%-40s
",'Name','Access','Comment'); $attr=$ref->getProperties(); foreach($attras$row){ printf("%-15s%-10s%-40s
",$row->getName(),getAccess($row),getComment($row)); } echo"常量列表:
"; printf("%-15s%-10s
",'Name','Value'); $const=$ref->getConstants(); foreach($constas$key=>$val){ printf("%-15s%-10s
",$key,$val); } echo"
"; echo"方法列表
"; printf("%-15s%-10s%-30s%-40s
",'Name','Access','Params','Comment'); $methods=$ref->getMethods(); foreach($methodsas$row){ printf("%-15s%-10s%-30s%-40s
",$row->getName(),getAccess($row),getParams($row),getComment($row)); } //获取权限 functiongetAccess($method) { if($method->isPublic()){ return'Public'; } if($method->isProtected()){ return'Protected'; } if($method->isPrivate()){ return'Private'; } } //获取方法参数信息 functiongetParams($method) { $str=''; $parameters=$method->getParameters(); foreach($parametersas$row){ $str.=$row->getName().','; if($row->isDefaultValueAvailable()){ $str.="Default:{$row->getDefaultValue()}"; } } return$str?$str:''; } //获取注释 functiongetComment($var) { $comment=$var->getDocComment(); //简单的获取了第一行的信息,这里可以自行扩展 preg_match('/\*(.*)*?/',$comment,$res); returnisset($res[1])?$res[1]:''; }
输出结果:
Student:
属性列表:
NameAccessComment
idPublic用户ID
常量列表:
NameValue
NORMAL1
FORBIDDEN2
方法列表
NameAccessParamsComment
getIdPublic获取id
setIdPublicid,Default:1
2.实现MVC架构
现在好多框架都是MVC的架构,根据路由信息定位控制器($controller)和方法($method)的名称,之后使用反射实现自动调用。
$class=newReflectionClass(ucfirst($controller).'Controller'); $controller=$class->newInstance(); if($class->hasMethod($method)){ $method=$class->getMethod($method); $method->invokeArgs($controller,$arguments); }else{ thrownewException("{$controller}controllermethod{$method}notexists!"); }
3.实现单元测试
一般情况下我们会对函数和类进行测试,判断其是否能够按我们预期返回结果,我们可以用反射实现一个简单通用的类测试用例。
hasMethod($method)){ $method=$ref->getMethod($method); $res=$method->invokeArgs(new$class,$data); if($res===$assert){ echo"测试结果正确"; }; } } testEqual('Calc@plus',3,[1,2]); echo"
"; testEqual('Calc@minus',-1,[1,2]);
这是类的测试方法,也可以利用反射实现函数的测试方法。
invokeArgs(array('Dr','Phil')); ?>
这里只是我简单写的一个测试用例,PHPUnit单元测试框架很大程度上依赖了Reflection的特性,可以了解下。
4.配合DI容器解决依赖
Laravel等许多框架都是使用Reflection解决依赖注入问题,具体可查看Laravel源码进行分析。
下面我们代码简单实现一个DI容器演示Reflection解决依赖注入问题。
bulid(self::$data[$k]); } //获取实例 publicfunctionbulid($className) { //如果是匿名函数,直接执行,并返回结果 if($classNameinstanceofClosure){ return$className($this); } //已经是实例化对象的话,直接返回 if(is_object($className)){ return$className; } //如果是类的话,使用反射加载 $ref=newReflectionClass($className); //监测类是否可实例化 if(!$ref->isInstantiable()){ thrownewException('class'.$className.'notfind'); } //获取构造函数 $construtor=$ref->getConstructor(); //无构造函数,直接实例化返回 if(is_null($construtor)){ returnnew$className; } //获取构造函数参数 $params=$construtor->getParameters(); //解析构造函数 $dependencies=$this->getDependecies($params); //创建新实例 return$ref->newInstanceArgs($dependencies); } //分析参数,如果参数中出现依赖类,递归实例化 publicfunctiongetDependecies($params) { $data=[]; foreach($paramsas$param) { $tmp=$param->getClass(); if(is_null($tmp)){ $data[]=$this->setDefault($param); }else{ $data[]=$this->bulid($tmp->name); } } return$data; } //设置默认值 publicfunctionsetDefault($param) { if($param->isDefaultValueAvailable()){ return$param->getDefaultValue(); } thrownewException('nodefaultvalue!'); } } classDemo { publicfunction__construct(Calc$calc) { echo$calc->plus(1,2); } } classCalc { publicfunctionplus($a,$b) { return$a+$b; } publicfunctionminus($a,$b) { return$a-$b; } } $di=newDI(); $di->calc='Calc'; $di->demo='Demo'; $di->demo;//输出结果为3
更多关于PHP相关内容感兴趣的读者可查看本站专题:《php面向对象程序设计入门教程》、《PHP数组(Array)操作技巧大全》、《PHP基本语法入门教程》、《PHP运算与运算符用法总结》、《php字符串(string)用法总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》
希望本文所述对大家PHP程序设计有所帮助。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。