Die strukturelle Reflexion, auch Introspektion genannt, macht die Struktur eines objektorientierten Systems durch die Programmiersprache des Systems zugänglich. Dies ermöglicht das Schreiben von generischem Code, der zur Laufzeit Informationen über Klassen und deren Objekte abfragt und diese entsprechend verarbeitet. Diese Generizität wird beispielsweise für das Schreiben von Code- und Dokumentationsgeneratoren benötigt. Ferner bildet sie die Grundlage für Werkzeuge wie PHPUnit (Kapitel 4), die "fremden" Code analysieren und ausführen müssen.
Für den "Blick in das Innere" von Klassen und Objekten bietet PHP die so genannte Reflection API an, die die folgenden Klassen und Schnittstellen umfasst:
Reflector ist die Schnittstelle, die von allen
Klassen der Reflection API implementiert wird.
Reflection ist eine statische Hilfsklasse, die
die Arbeit mit Reflector-Objekten erleichtert.
ReflectionException ist die von Exception
abgeleitete Ausnahme-Klasse, die für das Signalisieren von Fehlern
innerhalb der Reflection API verwendet wird.
ReflectionExtension repräsentiert die Informationen
über eine PHP-Erweiterung.
ReflectionFunction repräsentiert die Informationen
über eine Funktion.
ReflectionParameter repräsentiert die Informationen
über einen Parameter einer Funktion oder Methode.
ReflectionClass repräsentiert die Informationen
über eine Klasse.
ReflectionObject ist eine Erweiterung von
ReflectionClass und repräsentiert die Informationen
über ein Objekt.
ReflectionMethod ist eine Erweiterung von
ReflectionFunction und repräsentiert die Informationen
über eine Methode.
ReflectionProperty repräsentiert die Informationen
über eine Instanzvariable einer Klasse oder eines Objektes.
Allen Klassen der Reflection API gemein ist die statische Methode
export(). Diese liefert eine textuelle Darstellung
des reflektierten Sprachobjekts.
Beispiel 1.36
zeigt ein entsprechendes Beispiel.
Beispiel 1.36: Verwendung von ReflectionClass::export()
<?php
class Klasse {
public $public;
protected $protected;
private $privateStatic;
public function methode(Klasse $objekt) {
$objekt = new ReflectionObject($objekt);
print $objekt->getName();
}
}
print ReflectionClass::export('Klasse');
?>Class [ <user> class Klasse ] {
@@ /home/sb/export.php 2-11
- Constants [0] {
}
- Static properties [0] {
}
- Static methods [0] {
}
- Properties [3] {
Property [ <default> public $public ]
Property [ <default> protected $protected ]
Property [ <default> private $privateStatic ]
}
- Methods [1] {
Method [ <user> public method methode ] {
@@ /home/sb/export.php 7 - 10
- Parameters [1] {
Parameter #0 [ <required> Klasse $objekt ]
}
}
}
}
Stellvertretend für die Klassen der Reflection API betrachten wir die
Klasse ReflectionClass. Diese bietet die folgenden
Methoden:
getFileName(), getStartLine(), getEndLine(),
getDocComment(), getExtension() und
getExtensionName() liefern Informationen über die
Deklaration der Klasse in einer Quelltextdatei beziehungsweise in
einer PHP-Erweiterung.
isInternal(), isUserDefined(), isInstantiable(),
isInterface(), isAbstract(), isFinal(),
getParentClass(), isSubclassOf(), implementsInterface()
und isIterateable() liefern Informationen über
Eigenschaften der Klasse wie beispielsweise Vererbungsbeziehungen.
getMethod(), getMethods(), getProperty(),
getProperties(), getConstants() und getConstant()
liefern beispielsweise Objekte der Klassen ReflectionMethod und
ReflectionProperty, um mit den Methoden, Instanzvariablen und
Konstanten einer Klasse zu arbeiten.
In Beispiel 1.37
erzeugen wir zunächst ein Objekt der Klasse ReflectionClass
für die Klasse Klasse aus
Beispiel 1.36.
Über die Methode getMethod() dieses Objektes gelangen
wir an ein Objekt der Klasse ReflectionMethod, das die
Methode Klasse::Methode repräsentiert. Diese Methode
können wir mit ReflectionMethod::invoke() ausführen. Als
ersten Parameter müssen wir das Objekt der zugehörigen Klasse (in
unserem Beispiel Klasse) übergeben, auf dem die Methode
ausgeführt werden soll.
[5]
Danach folgen die Parameter der Methode, die aufgerufen werden soll.
[6]
Beispiel 1.37: ReflectionClass und ReflectionMethod im Einsatz
<?php
require_once 'Klasse.php';
$klasse = new ReflectionClass('Klasse');
$objekt = new Klasse;
$methode = $klasse->getMethod('methode');
$methode->invoke($objekt, $objekt);
?>Klasse
[5]
Handelt es sich bei der Methode, die über
ReflectionMethod::invoke() aufgerufen werden soll, um
eine Klassenmethode, so ist NULL anstelle eines
Objektes zu übergeben.
[6]
In PHP 5.1 wird es eine neue Methode invokeArgs()
geben, der man die Parameter der aufzurufenden Methode nicht
einzeln, sondern als Array übergeben kann.