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(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。