Forum und email

リフレクション

はじめに

PHP 5には完全なリフレクション APIが付属しており、 クラス、インターフェイス、関数、メソッド、そしてエクステンションについて リバースエンジニアリングを行うことができます。 さらに、このリフレクション APIは関数、クラス、メソッドに 関するドキュメントコメントも取得することができます。

リフレクション APIは、Zend Engineのオブジェクト指向エクステンション で、以下のクラスから構成されています。

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

注意: これらのクラスに関する詳細については、次章を参照してください。

以下の例のコードを実行してみましょう。

Example#1 リフレクション 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 [ <optional> $message ]
        Parameter #1 [ <optional> $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 ] {
    }
  }
}

Reflector

Reflector は、 すべてのエクスポート可能なリフレクションクラスが実装しているインターフェイスです。

<?php
interface Reflector
{
    public 
string __toString()
    public static 
string export()
}
?>

ReflectionException

ReflectionException は標準の Exception を継承しており、 リフレクション API によって投げられます。 固有のメソッドやプロパティは導入されていません。

ReflectionFunction

ReflectionFunctionクラスにより、 関数のリバースエンジニアリングが可能となります。

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

親クラスであるReflectionFunctionAbstract にも、 invoke() および invokeArgs()export()isDisabled() を除くすべてのメソッドが存在します。

注意: getNumberOfParameters()getNumberOfRequiredParameters() は PHP 5.0.3 で追加され、 invokeArgs() は PHP 5.1.0 で追加されました。

関数の内部を調べるために、まず、 ReflectionFunctionクラスのインスタンスを 生成する必要があります。 次にこのインスタンスの上のメソッドのどれかをコールすることができます。

Example#2 ReflectionFunctionクラスの使用法

<?php
/**
 * 簡単なカウンタ
 *
 * @return    int
 */
function counter()
{
    static 
$c 0;
    return 
$c++;
}

// ReflectionFunction クラスのインスタンスを生成する
$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($statics1));
}

// 関数を呼び出す
printf("---> Invokation results in: ");
var_dump($func->invoke());


// export() メソッドを使用する方が良い知れない
echo "\nReflectionFunction::export() results:\n";
echo 
ReflectionFunction::export('counter');
?>

注意: invoke()メソッドは、 call_user_func()と同様に 可変長の引数をとります。

ReflectionParameter

ReflectionParameterクラスは、 関数またはメソッドのパラメータに関する情報を取得します。

<?php
class ReflectionParameter implements Reflector
{
    final private 
__clone()
    public 
void __construct(string function, string parameter)
    public 
string __toString()
    public static 
string export