实例介绍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";
}
}
有点意思吧。