PHP 映射(反射)Reflection

时间:2022-06-01 20:02:24

介绍(Introduction)
PHP 5与一个API完全映射来以增加反向工程师类,接口,函数和方法的效率(性能)并加以扩展。另外, API映射并且为函数,类和方法提供获取文档注释的方法。
API映射是对Zend引擎一个面向对象的扩展。包括以下类:


<?php
class Reflection { }
interface Reflector { }
class 
ReflectionException extends Exception { }
class 
ReflectionFunction implements Reflector { }
class 
ReflectionParameter implements Reflector { }
class 
ReflectionMethod extends ReflectionFunction { }
class 
ReflectionClass implements Reflector { }
class 
ReflectionObject extends ReflectionClass { }
class 
ReflectionProperty implements Reflector { }
class 
ReflectionExtension implements Reflector { }
?> 


注:为了详细了解这些类,请看下一章。 如果我们将执行如下例子的代码:
例子 19-32.API映射的基本用法

<?php
Reflection
::export(new ReflectionClass('Exception'));
?> 


上例将输出:

Class [ <internal> class Exception ] {
  - Constants [0] { }
  - Static properties [0] { }
  - Static methods [0] { }
  - Properties [6] {
    Property [ <default> protected $message ]
    Property [ <default> private $string ]
    Property [ <default> protected $code ]
    Property [ <default> protected $file ]
    Property [ <default> protected $line ]
    Property [ <default> private $trace ]
  }
  - Methods [9] {
    Method [ <internal> final private method __clone ] { }
    Method [ <internal> <ctor> public method __construct ] {
      - Parameters [2] {
        Parameter #0 [ <required> $message ]
        Parameter #1 [ <required> $code ]
      }
    }
    Method [ <internal> final public method getMessage ] {  }
    Method [ <internal> final public method getCode ] {  }
    Method [ <internal> final public method getFile ] {  }
    Method [ <internal> final public method getLine ] {  }
    Method [ <internal> final public method getTrace ] {  }
    Method [ <internal> final public method getTraceAsString ] { }
    Method [ <internal> public method __toString ] { }
  }
}

异常映射(ReflectionException)
ReflectionException 扩展标准异常并由API映射抛出。引入了非特定方法或属性。
映射函数(ReflectionFunction)
ReflectionFunction类允许你反向设计函数。

<?php
class ReflectionFunction implements Reflector
{
    
final private __clone()
    
public object __construct(string name)
    
public string __toString()
    
public static string export()
    
public string getName()
    
public bool isInternal()
    
public bool isUserDefined()
    
public string getFileName()
    
public int getStartLine()
    
public int getEndLine()
    
public string getDocComment()
    
public array getStaticVariables()
    
public mixed invoke(mixedargs)
    
public mixed invokeArgs(array args)
    
public bool returnsReference()
    
public ReflectionParameter[] getParameters()
    
public int getNumberOfParameters()
    
public int getNumberOfRequiredParameters()
}
?> 


注:getNumberOfParameters()和getNumberOfRequiredParameters()在 PHP5.0.3中增加,而invokeArgs()是在PHP5.1.0中增加。
为内省一个函数,您必须首先创建ReflectionFunction 类的一个实例。您可以随后访问这个实例中的任何上述方法。
例子 19-33. 使用ReflectionFunction 类

<?php
/** A simple counter
 * @return  int  */
function counter() 
{   static 
$c 0;
    return 
$c++;
}
// Create an instance of the Reflection_Function class
$func = new ReflectionFunction('counter');
// Print out basic information
printf(
    
"===> The %s function '%s'/n".
    
"     declared in %s/n".
    
"     lines %d to %d/n",
    
$func->isInternal() ? 'internal' 'user-defined',
    
$func->getName(),
    
$func->getFileName(),
    
$func->getStartLine(),
    
$func->getEndline()
);
// Print documentation comment
printf("--->Documentation:/n%s/n",var_export($func->getDocComment(),1));
if (
$statics=$func->getStaticVariables())//Print static variables if existant
{  printf("--->Static variables:%s/n",var_export($statics,1));  }
printf("--->Invokation results in:");//Invoke the function
var_dump($func->invoke());
//you may prefer to use the export() method
echo "/nReflectionFunction::export() results:/n";
echo 
ReflectionFunction::export('counter');
?> 


注:方法invoke()通过象call_user_func()这样的函数接受自变量的一个变化的数值。
映射参数 (ReflectionParameter)
ReflectionParameter类取回一个函数或方法的参数的信息。

<?php
class ReflectionParameter implements Reflector
{
    
final private __clone()
    
public object __construct(string name)
    
public string __toString()
    
public static string export()
    
public string getName()
    
public bool isPassedByReference()
    
public ReflectionClass getClass()
    
public bool isArray()
    
public bool allowsNull()
    
public bool isOptional()
    
public bool isDefaultValueAvailable()
    
public mixed getDefaultValue()
}
?> 


注: 在PHP 5.0.3中增加了getDefaultValue(), isDefaultValueAvailable()和isOptional(),而isArray()则是在PHP5.1.0中增加的。
为内省函数参数,你必须首先创建ReflectionFunction或ReflectionMethod类的一个实例,然后用getParameters()方法来返回一个数组型参数。
例子 19-34. Using the ReflectionParameter class

<?php
function foo($a$b$c) { }
function 
bar(Exception $a, &$b$c) { }
function 
baz(ReflectionFunction $a$b 1$c null) { }
function 
abc() { }
//通过命令行用给定的参数创建ReflectionFunction的一个实例   
$reflect = new ReflectionFunction($argv[1]);
echo 
$reflect;
foreach (
$reflect->getParameters() as $i => $param)
{    
printf"-- Parameter #%d: %s {/n".
        
"   Class: %s/n".
        
"   Allows NULL: %s/n".
        
"   Passed to by reference: %s/n".
        
"   Is optional?: %s/n".
        
"}/n",
        
$i
        
$param->getName(),
        
var_export($param->getClass(), 1),
        
var_export($param->allowsNull(), 1),
        
var_export($param->isPassedByReference(), 1),
        
$param->isOptional() ? 'yes' 'no');
}
?> 


映射类(ReflectionClass)
ReflectionClass类允许你反向设计类。

<?php
class ReflectionClass implements Reflector
{   final private __clone()
    
public object __construct(string name)
    
public string __toString()
    
public static string export()
    
public string getName()
    
public bool isInternal()
    
public bool isUserDefined()
    
public bool isInstantiable()
    
public bool hasConstant(string name)
    
public bool hasMethod(string name)
    
public bool hasProperty(string name)
    
public string getFileName()
    
public int getStartLine()
    
public int getEndLine()
    
public string getDocComment()
    
public ReflectionMethod getConstructor()
    
public ReflectionMethod getMethod(string name)
    
public ReflectionMethod[] getMethods()
    
public ReflectionProperty getProperty(string name)
    
public ReflectionProperty[] getProperties()
    
public array getConstants()
    
public mixed getConstant(string name)
    
public ReflectionClass[] getInterfaces()
    
public bool isInterface()
    
public bool isAbstract()
    
public bool isFinal()
    
public int getModifiers()
    
public bool isInstance(stdclass object)
    
public stdclass newInstance(mixedargs)
    
public ReflectionClass getParentClass()
    
public bool isSubclassOf(ReflectionClass class)
    
public array getStaticProperties()
    
public mixed getStaticPropertyValue(string name [, mixed default])
    
public void setStaticPropertyValue(string namemixed value)
    
public array getDefaultProperties()
    
public bool isIterateable()
    
public bool implementsInterface(string name)
    
public ReflectionExtension getExtension()
    
public string getExtensionName()
}
?> 


PHP 映射(反射)ReflectionHP5.1.0中增加了hasConstant(), hasMethod(), hasProperty(), getStaticPropertyValue()和 setStaticPropertyValue()。
为了内省一个类,你必须首先创建ReflectionClass类的一个实例,你可以随后访问这个实例任何上述方法。
例子 19-35. 使用ReflectionClass 的类

<?php
interface Serializable  
{    // ...}
class Object {    // ...}
/** A counter class */
class Counter extends Object implements Serializable 
{   const START 0;
    
private static $c Counter::START;
    
/**Invoke counter
     * @access  public
     * @return  int */
    
public function count() {  return self::$c++;  }
}
// Create an instance of the ReflectionClass class
$class = new ReflectionClass('Counter');
// Print out basic information
printf("===> The %s%s%s %s '%s' [extends %s]/n" .
    
"     declared in %s/n" .
    
"     lines %d to %d/n" .
    
"     having the modifiers %d [%s]/n",
        
$class->isInternal() ? 'internal' 'user-defined',
        
$class->isAbstract() ? ' abstract' '',
        
$class->isFinal() ? ' final' '',
        
$class->isInterface() ? 'interface' 'class',
        
$class->getName(),
        
var_export($class->getParentClass(), 1),
        
$class->getFileName(),
        
$class->getStartLine(),
        
$class->getEndline(),
        
$class->getModifiers(),
        
implode(' 'Reflection::getModifierNames($class->getModifiers()))
);
// Print documentation comment
printf("--->Documentation:/n %s/n",var_export($class->getDocComment(),1));
// Print which interfaces are implemented by this class
printf("--->Implements:/n %s/n",var_export($class->getInterfaces(),1));
// Print class constants
printf("--->Constants:%s/n",var_export($class->getConstants(),1));
// Print class properties
printf("--->Properties:%s/n",var_export($class->getProperties(),1));
// Print class methods
printf("--->Methods:%s/n",var_export($class->getMethods(),1));
// If this class is instantiable, create an instance
if ($class->isInstantiable()) 
{   
$counter $class->newInstance();
    echo 
'---> $counter is instance? '
    echo 
$class->isInstance($counter) ? 'yes' 'no';
    echo 
"/n---> new Object() is instance? ";
    echo 
$class->isInstance(new Object()) ? 'yes' 'no';
}
?> 


注:方法newInstance()通过象call_user_func()这样的函数接受自变量的一个变化的数值。
PHP 映射(反射)Reflectionclass=new ReflectionClass('Foo');$class->isInstance($arg)等价于$arg instanceof Foo或is_a($arg, 'Foo').
映射方法(ReflectionMethod)
ReflectionMethod类允许你反向设计类方法。

<?php
class ReflectionMethod extends ReflectionFunction
{   public __construct(mixed class, string name)
    
public string __toString()
    
public static string export()
    
public mixed invoke(stdclass objectmixedargs)
    
public mixed invokeArgs(stdclass object, array args)
    
public bool isFinal()
    
public bool isAbstract()
    
public bool isPublic()
    
public bool isPrivate()
    
public bool isProtected()
    
public bool isStatic()
    
public bool isConstructor()
    
public bool isDestructor()
    
public int getModifiers()
    
public ReflectionClass getDeclaringClass()
    
// Inherited from ReflectionFunction
    
final private __clone()
    
public string getName()
    
public bool isInternal()
    
public bool isUserDefined()
    
public string getFileName()
    
public int getStartLine()
    
public int getEndLine()
    
public string getDocComment()
    
public array getStaticVariables()
    
public bool returnsReference()
   
public ReflectionParameter[] getParameters()
    
public int getNumberOfParameters()
    
public int getNumberOfRequiredParameters()
}
?> 


为了内省一个方法,你必须首先创建ReflectionMethod类的一个实例。你可以随后访问这个实例任何上述方法。
例子 19-36. Using the ReflectionMethod class

<?php
class Counter
{    private static $c 0;
    
/** Increment counter
     * @final
     * @static
     * @access  public
     * @return  int */    
final public static function increment(){ return ++self::$c; }
}
// Create an instance of the Reflection_Method class
$method = new ReflectionMethod('Counter','increment');
// Print out basic information
printf"===> The %s%s%s%s%s%s%s method '%s' (which is %s)/n" .
    
"     declared in %s/n" .
    
"     lines %d to %d/n" .
    
"     having the modifiers %d[%s]/n",
        
$method->isInternal() ? 'internal' 'user-defined',
        
$method->isAbstract() ? ' abstract' '',
        
$method->isFinal() ? ' final' '',
        
$method->isPublic() ? ' public' '',
        
$method->isPrivate() ? ' private' '',
        
$method->isProtected() ? ' protected' '',
        
$method->isStatic() ? ' static' '',
        
$method->getName(),
        
$method->isConstructor() ? 'the constructor' 'a regular method',
        
$method->getFileName(),
        
$method->getStartLine(),
        
$method->getEndline(),
        
$method->getModifiers(),
        
implode(' 'Reflection::getModifierNames($method->getModifiers()))
);
// Print documentation comment
printf("--->Documentation:/n %s/n",var_export($method->getDocComment(),1));
if(
$statics=$method->getStaticVariables())//Print static variables if existant
 
printf("--->Static variables:%s/n",var_export($statics,1)); }
printf("--->Invokation results in: ");//Invoke the method
var_dump($method->invoke(NULL));
?> 


注:试图调用私有的,保护的或抽象的方法将导致被invoke()方法抛出一个异常。静态方法如上所视,你必须通过NULL作为第一个自变量来invoke()。而非静态方法通过类的实例来调用。
映射属性(ReflectionProperty)
ReflectionProperty类允许你反向设计类属性。

<?php
class ReflectionProperty implements Reflector
{   final private __clone()
    
public __construct(mixed class, string name)
    
public string __toString()
    
public static string export()
    
public string getName()
    
public bool isPublic()
    
public bool isPrivate()
    
public bool isProtected()
    
public bool isStatic()
    
public bool isDefault()
    
public int getModifiers()
    
public mixed getValue(stdclass object)
    
public void setValue(stdclass objectmixed value)
    
public ReflectionClass getDeclaringClass()
    
public string getDocComment()
}
?> 


注: 在PHP 5.1.0中增加了getDocComment()方法。
为了内省一个属性,你必须首先创建ReflectionProperty类的一个实例,你可以随后访问这个实例的任何上述方法。
例子 19-37. Using the ReflectionProperty class

<?php
class String
{   public $length  5;   }
// Create an instance of the ReflectionProperty class
$prop=new ReflectionProperty('String','length');
// Print out basic information
printf"===> The%s%s%s%s property '%s' (which was %s)/n" .
    
"   having the modifiers %s/n",
        
$prop->isPublic() ? ' public' '',
        
$prop->isPrivate() ? ' private' '',
        
$prop->isProtected() ? ' protected' '',
        
$prop->isStatic() ? ' static' '',
        
$prop->getName(),
        
$prop->isDefault() ? 'declared at compile-time' 'created at run-time',
        
var_export(Reflection::getModifierNames($prop->getModifiers()),1)
);
$obj= new String();//Create an instance of String
printf("--->Value is: ");//Get current value
var_dump($prop->getValue($obj));
$prop->setValue($obj,10); // Change value
printf("---> Setting value to 10, new value is: ");
var_dump($prop->getValue($obj));
var_dump($obj); //Dump object
?> 


注:试图获得或设置私有的或保护的类属性的值将导致一个被抛出的异常。
映射扩展(ReflectionExtension)
ReflectionExtension类允许你反向设计扩展。你可以在使用get_loaded_extensions()运行的时候重新返回所有加载的扩展。

<?php
class ReflectionExtension implements Reflector 
{   final private __clone()
    
public __construct(string name)
    
public string __toString()
    
public static string export()
    
public string getName()
    
public string getVersion()
    
public ReflectionFunction[] getFunctions()
    
public array getConstants()
    
public array getINIEntries()
    
public ReflectionClass[] getClasses()
    
public array getClassNames()
}
?> 


为了内省一个扩展,你必须首先创建ReflectionExtension类的一个实例。你可以随后访问这个实例的任何上述方法。
例子 19-38. 使用ReflectionExtension 的类

<?php
// Create an instance of the ReflectionProperty class
$ext=new ReflectionExtension('standard');
// Print out basic information
printf("Name