Objekte vergleichen
Type Hinting
Klassen und Objekte (PHP 5)
PHP Manual

## Reflection

### Table of Contents

- Einleitung
- Die Reflector Interface
- Die ReflectionException Klasse
- Die ReflectionFunction Klasse
- Die ReflectionParameter Klasse
- Die Reflection Klasse
- Die ReflectionObject Klasse
- Die ReflectionMethod Klasse
- Die ReflectionProperty Klasse
- Die ReflectionExtension Klasse
- Erweitern der Reflection Klassen

### 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 name, bool 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($statics, 1));
}
// 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 parameter, bool 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 name, mixed 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 object, bool 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 name, bool 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($statics, 1));
}
// 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 name, bool 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 object, mixed 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($obj, 10);
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 name, bool 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->visibility= Reflection::getModifierNames($this->getModifiers());
}
}
/**
* Demoklasse #1
*
*/
class T {
protected function x() {}
}
/**
* Demoklasse #2
*
*/
class U extends T {
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

Objekte vergleichen
Type Hinting
Klassen und Objekte (PHP 5)
PHP Manual