实例介绍PHP的Reflection反射机制
PHP5添加了一项新的功能:Reflection。这个功能使得程序员可以reverse-engineerclass,interface,function,methodandextension。通过PHP代码,就可以得到某object的所有信息,并且可以和它交互。
假设有一个类Person:
classPerson{ /** *Forthesakeofdemonstration,we"resettingthisprivate */ private$_allowDynamicAttributes=false; /**type=primary_autoincrement*/ protected$id=0; /**type=varcharlength=255null*/ protected$name; /**type=textnull*/ protected$biography; publicfunctiongetId() { return$this->id; } publicfunctionsetId($v) { $this->id=$v; } publicfunctiongetName() { return$this->name; } publicfunctionsetName($v) { $this->name=$v; } publicfunctiongetBiography() { return$this->biography; } publicfunctionsetBiography($v) { $this->biography=$v; } }
通过ReflectionClass,我们可以得到Person类的以下信息:
1.常量Contants
2.属性PropertyNames
3.方法MethodNames
4.静态属性StaticProperties
5.命名空间Namespace
6.Person类是否为final或者abstract
只要把类名"Person"传递给ReflectionClass就可以了:
$class=newReflectionClass('Person');
获取属性(Properties):
$properties=$class->getProperties(); foreach($propertiesas$property){ echo$property->getName()."\n"; } //输出: //_allowDynamicAttributes //id //name //biography
默认情况下,ReflectionClass会获取到所有的属性,private和protected的也可以。如果只想获取到private属性,就要额外传个参数:
$private_properties=$class->getProperties(ReflectionProperty::IS_PRIVATE);
可用参数列表:
ReflectionProperty::IS_STATIC ReflectionProperty::IS_PUBLIC ReflectionProperty::IS_PROTECTED ReflectionProperty::IS_PRIVATE
如果要同时获取public和private属性,就这样写:ReflectionProperty::IS_PUBLIC|ReflectionProperty::IS_PROTECTED
应该不会感觉陌生吧。
通过$property->getName()可以得到属性名,通过getDocComment可以得到写给property的注释。
foreach($propertiesas$property){ if($property->isProtected()){ $docblock=$property->getDocComment(); preg_match('/type\=([a-z_]*)/',$property->getDocComment(),$matches); echo$matches[1]."\n"; } } //Output: //primary_autoincrement //varchar //text
有点不可思议了吧。竟然连注释都可以取到。
获取方法(methods):通过getMethods()来获取到类的所有methods。返回的是ReflectionMethod对象的数组。不再演示。
最后通过ReflectionMethod来调用类里面的method。
$data=array("id"=>1,"name"=>"Chris","biography"=>"IamamaPHPdeveloper"); foreach($dataas$key=>$value){ if(!$class->hasProperty($key)){ thrownewException($key."isnotavalidproperty"); } if(!$class->hasMethod("get".ucfirst($key))){ thrownewException($key."ismissingagetter"); } if(!$class->hasMethod("set".ucfirst($key))){ thrownewException($key."ismissingasetter"); } //Makeanewobjecttointeractwith $object=newPerson(); //Getthegettermethodandinvokeitwiththevalueinourdataarray $setter=$class->getMethod("set".ucfirst($key)); $ok=$setter->invoke($object,$value); //Getthesettermethodandinvokeit $setter=$class->getMethod("get".ucfirst($key)); $objValue=$setter->invoke($object); //Nowcompare if($value==$objValue){ echo"GetterorSetterhasmodifiedthedata.\n"; }else{ echo"GetterandSetterdoesnotmodifythedata.\n"; } }
有点意思吧。