PHP 5には完全なリフレクション APIが付属しており、
   クラス、インターフェイス、関数、メソッド、そしてエクステンションについて
   リバースエンジニアリングを行うことができます。
   さらに、このリフレクション APIは関数、クラス、メソッドに
   関するドキュメントコメントも取得することができます。
  
   リフレクション APIは、Zend Engineのオブジェクト指向エクステンション
   で、以下のクラスから構成されています。
  
注意: 
    これらのクラスに関する詳細については、次章を参照してください。
   
   以下の例のコードを実行してみましょう。
   
例 19-33. リフレクション 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 は標準の Exception を継承しており、
    リフレクション API によって投げられます。
    固有のメソッドやプロパティは導入されていません。
   
   ReflectionFunctionクラスにより、
   関数のリバースエンジニアリングが可能となります。
  
注意: 
     getNumberOfParameters() と
     getNumberOfRequiredParameters() は PHP 5.0.3
     で追加され、
     invokeArgs() は PHP 5.1.0 で追加されました。
    
   関数の内部を調べるために、まず、
   ReflectionFunctionクラスのインスタンスを
   生成する必要があります。
   次にこのインスタンスの上のメソッドのどれかをコールすることができます。
  
例 19-34. ReflectionFunctionクラスの使用法 
<?php /**  * 簡単なカウンタ  *  * @return    int  */ function counter() {     static $c = 0;     return $c++; }
  // Reflection_Function クラスのインスタンスを生成する $func = new ReflectionFunction('counter');
  // 基本情報を表示する 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() );
  // ドキュメントコメントを表示する printf("---> Documentation:\n %s\n", var_export($func->getDocComment(), 1));
  // static 変数があれば表示する if ($statics = $func->getStaticVariables()) {     printf("---> Static variables: %s\n", var_export($statics, 1)); }
  // 関数を呼び出す printf("---> Invokation results in: "); var_dump($func->invoke());
 
  // export() メソッドを使用する方が良い知れない echo "\nReflectionFunction::export() results:\n"; echo ReflectionFunction::export('counter'); ?>
 |  
  | 
   ReflectionParameterクラスは、
   関数またはメソッドのパラメータに関する情報を取得します。
  
注意: 
     getDefaultValue(),
     isDefaultValueAvailable(),
     isOptional()  は PHP 5.0.3 で追加され、
     isArray() は PHP 5.1.0で追加されました。
     getDeclaringFunction() および
     getPosition() は PHP 5.1.3 で追加されました。
   
   関数パラメータの内部を調べる際には、まず、
   ReflectionFunction クラスまたは
   ReflectionMethod クラスのインスタンスを
   作成する必要があります。
   次に、配列のパラメータを取得するために、そのインスタンスの
   getParameters()メソッドを使用してください。
  
例 19-35. ReflectionParameterクラスの使用 
<?php function foo($a, $b, $c) { } function bar(Exception $a, &$b, $c) { } function baz(ReflectionFunction $a, $b = 1, $c = null) { } function abc() { }
  // コマンドラインから与えられたパラメータを使って // Reflection_Function のインスタンスを生成する $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クラスにより、
   クラスのリバースエンジニアリングが可能となります。
  
注意: 
     hasConstant(), hasMethod(),
     hasProperty(), getStaticPropertyValue()
     および setStaticPropertyValue()
     は、PHP 5.1.0 で追加されました。
     また、newInstanceArgs() は PHP 5.1.3 で追加されました。
    
   クラスのイントロスペクションを行うには、まず
   ReflectionClass
   クラスのインスタンスを生成する必要があります。それから、
   このインスタンスのメソッドをコールしてください。
  
例 19-36. ReflectionClassクラスの使用法 
<?php interface Serializable {     // ... }
  class Object {     // ... }
  /**  * カウンタクラス  */ class Counter extends Object implements Serializable {     const START = 0;     private static $c = Counter::START;
      /**      * カウンタを呼び出す      *      * @access  public      * @return  int      */     public function count() {         return self::$c++;     } }
  // ReflectionClass クラスのインスタンスを生成する $class = new ReflectionClass('Counter');
  // 基本情報を表示する 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())) );
  // ドキュメントコメントを表示する printf("---> Documentation:\n %s\n", var_export($class->getDocComment(), 1));
  // このクラスが実装しているインターフェースを表示する printf("---> Implements:\n %s\n", var_export($class->getInterfaces(), 1));
  // クラス定数を表示する printf("---> Constants: %s\n", var_export($class->getConstants(), 1));
  // クラスプロパティを表示する printf("---> Properties: %s\n", var_export($class->getProperties(), 1));
  // クラスメソッドを表示する printf("---> Methods: %s\n", var_export($class->getMethods(), 1));
  // このクラスがインスタンス化可能な場合、インスタンスを生成する 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'; } ?>
 |  
  | 
注意: 
    $class = new ReflectionClass('Foo'); $class->isInstance($arg)
    は、$arg instanceof Foo または
    is_a($arg, 'Foo')と等価です。
   
    ReflectionObject クラスにより、
    オブジェクトのリバースエンジニアリングが可能となります。
   
   ReflectionMethodクラスにより、
   クラスメソッドのリバースエンジニアリングが可能となります。
  
   メソッドの内部を調べるために、まず、
   ReflectionMethodクラスのインスタンスを
   生成する必要があります。
   次にこのインスタンスの上のメソッドのどれかをコールすることができます。
  
例 19-37. ReflectionMethodクラスの使用 
<?php class Counter {     private static $c = 0;
      /**      * カウンタをインクリメントする      *      * @final      * @static      * @access  public      * @return  int      */     final public static function increment()     {         return ++self::$c;     } }
  // Reflection_Method クラスのインスタンスを生成する $method = new ReflectionMethod('Counter', 'increment');
  // 基本情報を表示する 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())) );
  // ドキュメントコメントを表示する printf("---> Documentation:\n %s\n", var_export($method->getDocComment(), 1));
  // static 変数があれば表示する if ($statics= $method->getStaticVariables()) {     printf("---> Static variables: %s\n", var_export($statics, 1)); }
  // メソッドを呼び出す printf("---> Invokation results in: "); var_dump($method->invoke(NULL)); ?>
 |  
  | 
注意: 
    private, protectedまたはabstractメソッドのinvokeを行うと、
    invoke()から例外がスローされます。
   
注意: 
    上記のstaticメソッドの場合、
    invoke()の最初の引数にNULLを渡す必要があります。
    staticでないメソッドの場合、ここにクラスのインスタンスを指定してください。
   
   ReflectionPropertyクラスにより、
   クラスプロパティに関する
   リバースエンジニアリングが可能となります。
  
   プロパティの内部を調べるために、まず、
   ReflectionPropertyクラスのインスタンスを
   生成する必要があります。
   次にこのインスタンスの上のメソッドのどれかをコールすることができます。
  
例 19-38. ReflectionPropertyクラスの使用 
<?php class String {     public $length  = 5; }
  // ReflectionProperty クラスのインスタンスを生成する $prop = new ReflectionProperty('String', 'length');
  // 基本情報を表示する 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) );
  // String のインスタンスを生成する $obj= new String();
  // 現在の値を取得する printf("---> Value is: "); var_dump($prop->getValue($obj));
  // 値を変更する $prop->setValue($obj, 10); printf("---> Setting value to 10, new value is: "); var_dump($prop->getValue($obj));
  // オブジェクトをダンプする var_dump($obj); ?>
 |  
  | 
注意: 
    privateまたはprotectedクラスプロパティの値の取得または設定を
    行うと、例外がスローされます。
   
   The ReflectionExtensionクラスにより、
   エクステンションのリバースエンジニアリングが可能となります。
   実行時にロードされている全てのエクステンションを
   get_loaded_extensions()により取得することができます。
  
   メソッドの内部を調べるために、まず、
   ReflectionExtensionクラスのインスタンスを
   生成する必要があります。
   次にこのインスタンスの上のメソッドのどれかをコールすることができます。
  
例 19-39. ReflectionExtensionクラスの使用 
<?php // ReflectionProperty クラスのインスタンスを生成する $ext = new ReflectionExtension('standard');
  // 基本情報を表示する printf(     "Name        : %s\n" .     "Version     : %s\n" .     "Functions   : [%d] %s\n" .     "Constants   : [%d] %s\n" .     "INI entries : [%d] %s\n" .     "Classes     : [%d] %s\n",         $ext->getName(),         $ext->getVersion() ? $ext->getVersion() : 'NO_VERSION',         sizeof($ext->getFunctions()),         var_export($ext->getFunctions(), 1),
          sizeof($ext->getConstants()),         var_export($ext->getConstants(), 1),
          sizeof($ext->getINIEntries()),         var_export($ext->getINIEntries(), 1),
          sizeof($ext->getClassNames()),         var_export($ext->getClassNames(), 1) ); ?>
 |  
  | 
   組み込みクラスの特別なバージョンを作成したい場合
   (例えば、、エクスポートする際に、色づけしたHTMLを作成したり、
   メソッドの代わりに簡単にアクセスできるメンバー変数を作成したり、
   補助的なメソッドを作成したり、)、
   Reflectionクラスを拡張することができます。
  
例 19-40. 組み込みクラスを拡張する 
<?php /**  * 独自の Reflection_Method クラス  */ class My_Reflection_Method extends ReflectionMethod {     public $visibility = '';
      public function __construct($o, $m)     {         parent::__construct($o, $m);         $this->visibility= Reflection::getModifierNames($this->getModifiers());     } }
  /**  * デモクラス #1  *  */ class T {     protected function x() {} }
  /**  * デモクラス #2  *  */ class U extends T {     function x() {} }
  // 基本情報を表示する var_dump(new My_Reflection_Method('U', 'x')); ?>
 |  
  | 
注意: 
    注意: Iコンストラクタを上書きした場合、
    挿入するコードの前に
    親クラスのコンストラクタをコールしわすれないようにしてください。
    これを怠ると、以下のようなエラーを発生します。
    
     Fatal error: Internal error: Failed to retrieve the reflection object