Klassen und Objekte (PHP 5)
PHP Manual

Reflection

Table of Contents

Einleitung

Php 5 bringt eine komplette Reflection API mit, die M�glichkeiten bietet, um Klassen, Interfaces, Funktionen und Methoden ebenso wie auch Extensions zur�ckzuentwickeln. Zus�tzlich bietet die Reflection API Wege, dokumentarische Kommentare von Funktionen, Klassen und Methoden abzufragen.

Die Refelection API ist eine objektorientierte Erweiterung der Zend Engine, bestehend aus den folgenden Klassen:

<?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 { }
?>

Hinweis: F�r detailierte Erl�uterungen dieser Klassen werfen Sie einen Blick auf die n�chsten Kapitel.

Wenn wir den unten stehenden Beispielcode ausf�hren w�rden:

Beispiel #1 Grundlegende Nutzung der Reflection API

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

Das oben gezeigte Beispiel erzeugt folgende Ausgabe:

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 ist ein von allen Reflektionsklassen implementiertes Interface.

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

ReflectionException

ReflectionException erweitert die normale Exception und wird von der Reflection API geworfen. Es werden keine spezifischen Methoden oder Eigenschaften eingef�hrt.

ReflectionFunction

Die ReflectionFunction Klasse l�sst Sie Funktionen zur�ckentwickeln.

<?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()
}
?>

Die Elternklasse ReflectionFunctionAbstract hat die gleichen Methoden mit Ausnahme von invoke(), invokeArgs(), export() und isDisabled().

Hinweis: getNumberOfParameters() und getNumberOfRequiredParameters() wurden in PHP 5.0.3 hinzugef�gt, w�hrend invokeArgs() in PHP 5.1.0 neu hinzukam.

Um einen Blick in eine Funktion zu werfen, muss man erst eine Instanz der Klasse ReflectionFunction erzeugen. Danach kann man jede der oben aufgef�hrten Methoden dieser Instanz aufrufen.

Beispiel #2 Die ReflectionFunction Klasse benutzen

<?php
/**
 * Ein einfacher Z�hler
 *
 * @return    int
 */
function counter()
{
    static 
$c 0;
    return 
$c++;
}

// Erzeuge eine neue Instanz der ReflectionFunction Klasse
$func = new ReflectionFunction('counter');

// Grundlegende Informationen ausgeben
printf(
    
"===> Die %s Funktion '%s'\n".
    
"     ist deklariert in %s\n".
    
"     Zeilen %d bis %d\n",
    
$func->isInternal() ? 'interne' 'benutzerdefinierte',
    
$func->getName(),
    
$func->getFileName(),
    
$func->getStartLine(),
    
$func->getEndline()
);

// Dokumentaischen Kommentar ausgeben
printf("---> Dokumentation:\n %s\n"var_export($func->getDocComment(), 1));

// Statische Variablen ausgeben, wenn welche existieren
if ($statics $func->getStaticVariables())
{
    
printf("---> Statische Variablen: %s\n"var_export($statics1));
}

// Die Funktion aufrufen
printf("---> Der Aufruf gibt zur�ck: ");
var_dump($func->invoke());


// Sie k�nnten bevorzugen die export() Methode zu verwenden
echo "\nReflectionFunction::export() gibt zur�ck:\n";
echo 
ReflectionFunction::export('counter');
?>

Hinweis: Die Methode invoke() akzeptiert eine variable Anzahl von Argumenten, welche genau wie von call_user_func() an die Funktion �bergeben werden.

ReflectionParameter

Die ReflectionParameter Klasse fr�gt Informationen �ber die Parameter einer Funktion oder Methode ab.

<?php
class ReflectionParameter implements Reflector
{
    final private 
__clone()
    public 
void __construct(string function, string parameter)
    public 
string __toString()
    public static 
string export(mixed function, mixed parameterbool return)
    public 
string getName()
    public 
bool isPassedByReference()
    public 
ReflectionClass getDeclaringClass()
    public 
ReflectionClass getClass()
    public 
bool isArray()
    public 
bool allowsNull()
    public 
bool isPassedByReference()
    public 
bool isOptional()
    public 
bool isDefaultValueAvailable()
    public 
mixed getDefaultValue()
}
?>

Hinweis: getDefaultValue(), isDefaultValueAvailable() und isOptional() wurden in PHP 5.0.3 hinzugef�gt, w�hrend isArray() in PHP 5.1.0 neu ist. getDeclaringFunction() und getPosition() wurden in PHP 5.1.3 hinzugef�gt.

Um einen Blick in Funktionsparameter zu werfen, muss man zuerst eine Instanz der Klassen ReflectionFunction oder ReflectionMethod erzeugen und kann dann deren getParameters() Methode verwenden, um ein Array ihrer Parameter abzufragen.

Beispiel #3 Die ReflectionParameter Klasse verwenden

<?php
function foo($a$b$c) { }
function 
bar(Exception $a, &$b$c) { }
function 
baz(ReflectionFunction $a$b 1$c null) { }
function 
abc() { }

// Erzeuge eine Instanz von ReflectionFunction mit dem
// auf der Kommandozeile ï¿½bergebenen Parameter
$reflect = new ReflectionFunction($argv[1]);

echo 
$reflect;

foreach (
$reflect->getParameters() as $i => $param) {
    
printf(
        
"-- Parameter #%d: %s {\n".
        
"   Klasse: %s\n".
        
"   Erlaubt NULL: %s\n".
        
"   Als Referenz ï¿½bergeben: %s\n".
        
"   Ist optional?: %s\n".
        
"}\n",
        
$i,
        
$param->getName(),
        
var_export($param->getClass(), 1),
        
var_export($param->allowsNull(), 1),
        
var_export($param->isPassedByReference(), 1),
        
$param->isOptional() ? 'ja' 'nein'
    
);
}
?>

ReflectionClass

Die ReflectionClass Klasse erlaubt es, Klassen und Interfaces zur�ckzuentwickeln.

<?php
class ReflectionClass implements Reflector
{
    final private 
__clone()
    public 
void __construct(string name)
    public 
string __toString()
    public static 
string export(mixed class, bool return)
    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(mixed args)
    public 
stdclass newInstanceArgs(array args)
    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()
}
?>

Hinweis: hasConstant(), hasMethod(), hasProperty(), getStaticPropertyValue() und setStaticPropertyValue() wurden in PHP 5.1.0 hinzugef�gt, w�hrend newInstanceArgs() in PHP 5.1.3 dazu kam.

Um einen Blick in eine Klasse zu werfen, muss man zuerst eine Instanz der Klasse ReflectionClass erzeugen. Man kann danach jede der oben angef�hrten Methoden der Instanz verwenden.

Beispiel #4 Die ReflectionClass Klasse verwenden

<?php
interface Serializable
{
    
// ...
}

class 
Object
{
    
// ...
}

/**
 * Eine Z�hlerklasse
 */
class Counter extends Object implements Serializable
{
    const 
START 0;
    private static 
$c Counter::START;

    
/**
     * Z�hler aufrufen
     *
     * @access  public
     * @return  int
     */
    
public function count() {
        return 
self::$c++;
    }
}

// Eine Instanz der Klasse ReflectionClass erzeugen
$class = new ReflectionClass('Counter');

// Grundlegende Informationen ausgeben
printf(
    
"===> %s%s%s %s '%s' [extends %s]\n" .
    
"     deklariert in %s\n" .
    
"     Zeilen %d bis %d\n" .
    
"     hat die Modifizierer %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()))
);

// Dokumentarischen Kommentar ausgeben
printf("---> Dokumentation:\n %s\n"var_export($class->getDocComment(), 1));

// Ausgeben, welche Interfaces von der Klasse implementiert werden
printf("---> Implementiert:\n %s\n"var_export($class->getInterfaces(), 1));

// Klassenkonstanten ausgeben
printf("---> Konstanten: %s\n"var_export($class->getConstants(), 1));

// Klasseneigenschaften ausgeben
printf("---> Eigenschaften: %s\n"var_export($class->getProperties(), 1));

// Klassenmethoden ausgeben
printf("---> Methoden: %s\n"var_export($class->getMethods(), 1));

// Wenn die Klassen instantiierbar ist, erzeuge eine Instanz
if ($class->isInstantiable()) {
    
$counter $class->newInstance();

    echo 
'---> Ist $counter Instanz? ';
    echo 
$class->isInstance($counter) ? 'ja' 'nein';

    echo 
"\n---> ist new Object() Instanz? ";
    echo 
$class->isInstance(new Object()) ? 'ja' 'nein';
}
?>

Hinweis: Die Methode newInstance() akzeptiert eine variable Anzahl von Argumenten, welche der Funktion genau wie in call_user_func() �bergeben werden.

Hinweis: $class = new ReflectionClass('Foo'); $class->isInstance($arg) ist �quivalent zu $arg instanceof Foo oder is_a($arg, 'Foo').

ReflectionObject

Die Klasse ReflectionObject erlaubt das Zur�ckentwickeln von Objekten.

<?php
class ReflectionObject extends ReflectionClass
{
    final private 
__clone()
    public 
void __construct(mixed object)
    public 
string __toString()
    public static 
string export(mixed objectbool return)
}
?>

ReflectionMethod

Die ReflectionMethod Klasse erlaubt es, Klassenmethoden zur�ckzuentwickeln.

<?php
class ReflectionMethod extends ReflectionFunctionAbstract implements Reflector
{
    public 
__construct(mixed class, string name)
    public 
string __toString()
    public static 
string export(mixed class, string namebool return)
    public 
mixed invoke(stdclass object [, mixed args [, ...]])
    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()

    
// Ererbt von ReflectionFunctionAbstract
    
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()
}
?>

Um einen Blick in eine Methode zu werfen, muss man zuerst eine Instanz der ReflectionMethod Klasse erzeugen. Man kann dann jede der oben aufgef�hrten Methoden dieser Instanz aufrufen.

Beispiel #5 Die ReflectionMethod Klasse verwenden

<?php
class Counter
{
    private static 
$c 0;

    
/**
     * Z�hler erh�hen
     *
     * @final
     * @static
     * @access  public
     * @return  int
     */
    
final public static function increment()
    {
        return ++
self::$c;
    }
}

// Erzeuge eine Instanz der ReflectionMethod Klasse
$method = new ReflectionMethod('Counter''increment');

// Grundlegende Informationen ausgeben
printf(
    
"===> Die %s%s%s%s%s%s%s Methode '%s' (welche %s ist)\n" .
    
"     deklariert in %s\n" .
    
"     Zeilen %d bis %d\n" .
    
"     hat die Modifizierer %d[%s]\n",
        
$method->isInternal() ? 'interne' 'benutzerdefinierte',
        
$method->isAbstract() ? ' abstract' '',
        
$method->isFinal() ? ' final' '',
        
$method->isPublic() ? ' public' '',
        
$method->isPrivate() ? ' private' '',
        
$method->isProtected() ? ' protected' '',
        
$method->isStatic() ? ' static' '',
        
$method->getName(),
        
$method->isConstructor() ? 'der Konstruktor' 'eine normale Methode',
        
$method->getFileName(),
        
$method->getStartLine(),
        
$method->getEndline(),
        
$method->getModifiers(),
        
implode(' 'Reflection::getModifierNames($method->getModifiers()))
);

// Dokumentarischen Kommentar ausgeben
printf("---> Dokumentation:\n %s\n"var_export($method->getDocComment(), 1));

// Statische Variablen ausgeben, falls welche existieren
if ($statics$method->getStaticVariables()) {
   
printf("---> Statische Variablen: %s\n"var_export($statics1));
}

// Die Methode aufrufen
printf("---> Aufruf gibt zur�ck: ");
var_dump($method->invoke(NULL));
?>

Hinweis: Der Versuch, eine private, protected oder abstract Methode aufzurufen, wird darin enden, dass eine Exception aus der invoke() Methode geworfen wird.

Hinweis: F�r statische Methoden sollten Sie, wie man oben sieht, NULL als erstes Argument von invoke() �bergeben. F�r nicht statische Methoden �bergeben Sie eine Instanz der Klasse.

ReflectionProperty

Die ReflectionProperty Klasse l�sst Sie Klasseneigenschaften zur�ckentwickeln.

<?php
class ReflectionProperty implements Reflector
{
    final private 
__clone()
    public 
__construct(mixed class, string name)
    public 
string __toString()
    public static 
string export(mixed class, string namebool return)
    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()
}
?>

Hinweis: getDocComment() wurde in PHP 5.1.0 hinzugef�gt.

Um einen Blick in eine Eigenschaft zu werfen, m�ssen Sie zuerst eine Instanz der Klasse ReflectionProperty erzeugen. Danach k�nnen Sie jede der oben angef�hrten Methoden der Instanz aufrufen.

Beispiel #6 Die ReflectionProperty Klasse verwenden

<?php
class String
{
    public 
$laenge  5;
}

// Erzeuge eine Instanz der Klasse ReflectionPropety
$prop = new ReflectionProperty('String''laenge');

// Grundlegende Informationen ausgeben
printf(
    
"===> Die %s%s%s%s Eigenschaft '%s' (welche %s wurde)\n" .
    
"     hat die Modizifierer %s\n",
        
$prop->isPublic() ? ' public' '',
        
$prop->isPrivate() ? ' private' '',
        
$prop->isProtected() ? ' protected' '',
        
$prop->isStatic() ? ' static' '',
        
$prop->getName(),
        
$prop->isDefault() ? 'zur Kompilierungszeit deklariert' :
                             
'zur Laufzeit erzeugt',
        
var_export(Reflection::getModifierNames($prop->getModifiers()), 1)
);

// Eine Instanz von String erzeugen
$obj= new String();

// Aktuellen Wert abfragen
printf("---> Wert ist: ");
var_dump($prop->getValue($obj));

// Wert ï¿½ndern
$prop->setValue($obj10);
printf("---> Setze Wert auf 10, neuer Wert ist: ");
var_dump($prop->getValue($obj));

// Objekt ausgeben
var_dump($obj);
?>

Hinweis: Der Versuch, den Wert einer private oder protected Klasseneigenschaft zu lesen oder zu setzen, wird darin enden, dass eine Exception geworfen wird.

ReflectionExtension

Die ReflectionExtension Klasse l�sst Sie Extensions zur�ckentwickeln. Man kann alle geladenen Extensions zur Laufzeit mittels get_loaded_extensions() abrufen.

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

Um einen Blick in eine Extension zu werfen, muss man zuerst eine Instanz der Klasse ReflectionExtension erzeugen. Danach kann man alle oben aufgef�hrten Methoden der Instanz aufrufen.

Beispiel #7 Die ReflectionExtension Klasse verwenden

<?php
// Erzeuge eine neue Instanz der ReflectionExtension Klasse
$ext = new ReflectionExtension('standard');

// Grundlegende Informationen ausgeben
printf(
    
"Name         : %s\n" .
    
"Version      : %s\n" .
    
"Funktionen   : [%d] %s\n" .
    
"Konstanten   : [%d] %s\n" .
    
"INI Eintr�ge : [%d] %s\n" .
    
"Klassen      : [%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)
);
?>

Die Reflection Klassen erweitern

F�r den Fall, dass Sie spezialisierte Versionen der eingebauten Klassen erzeugen wollen (zum Beispiel, um kolorierte HTML Ausgaben zu erzeugen oder leicht zug�ngliche Klassenvariablen oder -methoden oder Hilfmethoden hinzuzuf�gen), k�nnen Sie fortfahren und die Klassen ableiten.

Beispiel #8 Erweiterung der eingebauten Klassen

<?php
/**
 * M_Reflection_Method Klasse
 */
class My_Reflection_Method extends ReflectionMethod
{
    public 
$visibility = array();

    public function 
__construct($o$m)
    {
        
parent::__construct($o$m);
        
$this->visibilityReflection::getModifierNames($this->getModifiers());
    }
}

/**
 * Demoklasse #1
 *
 */
class {
    protected function 
x() {}
}

/**
 * Demoklasse #2
 *
 */
class extends {
    function 
x() {}
}

// Informationen ausgeben
var_dump(new My_Reflection_Method('U''x'));
?>

Hinweis: Achtung: Wenn Sie den Konstruktor �berschreiben, denken Sie daran, den Vaterkonstruktor _vor_ jedem anderen Code den Sie hinzuf�gen aufzurufen. Unterlassung wird zu folgendem Ergebnis f�hren: Fatal error: Internal error: Failed to retrieve the reflection object


Klassen und Objekte (PHP 5)
PHP Manual