Start · Sprachen · PHP · Referenz · ReflectionFunctionAbstract

ReflectionFunctionAbstract

Klasse

Abstrakte Basisklasse für <code>ReflectionFunction</code> und <code>ReflectionMethod</code>, die gemeinsame Methoden zur Inspektion von Funktionen und Methoden bereitstellt.

seit PHP 5.2.0 Kategorie: oop

Signatur

abstract class ReflectionFunctionAbstract implements Reflector

Beschreibung

ReflectionFunctionAbstract ist die abstrakte Elternklasse der PHP-Reflection-API für ausführbare Einheiten. Sie enthält alle Methoden, die sowohl für freistehende Funktionen (ReflectionFunction) als auch für Klassenmethoden (ReflectionMethod) relevant sind. Da sie abstrakt ist, kann sie nicht direkt instanziiert werden.

Über diese Klasse lassen sich zur Laufzeit detaillierte Metainformationen über eine Funktion oder Methode abrufen: Parameterlisten, Rückgabetypen, Docblock-Kommentare, Datei- und Zeilennummern, Closure-Bindungen sowie ob eine Funktion etwa intern (built-in), variadic, deprecated oder einen Referenzrückgabe besitzt.

Typische Einsatzgebiete sind Dependency-Injection-Container, Test-Frameworks, Code-Generatoren und Dokumentationswerkzeuge, die zur Laufzeit die Signatur einer Funktion analysieren müssen – z. B. um automatisch Argumente aufzulösen oder API-Dokumentation zu erzeugen.

Da ReflectionFunctionAbstract selbst nicht instanziierbar ist, arbeitet man stets mit einer ihrer konkreten Unterklassen: ReflectionFunction für normale Funktionen und Closures, ReflectionMethod für Methoden einer Klasse oder eines Objekts.

Beispiele

Parameterliste einer Funktion inspizieren

<?php
function berechnePreis(float $netto, float $mwstSatz = 0.19, bool $runden = true): float {
    $brutto = $netto * (1 + $mwstSatz);
    return $runden ? round($brutto, 2) : $brutto;
}

$ref = new ReflectionFunction('berechnePreis');

echo "Funktion: " . $ref->getName() . PHP_EOL;
echo "Parameter:" . PHP_EOL;

foreach ($ref->getParameters() as $param) {
    $typ  = $param->hasType() ? (string) $param->getType() . ' ' : '';
    $default = $param->isOptional()
        ? ' = ' . var_export($param->getDefaultValue(), true)
        : '';
    echo "  \${$typ}{$param->getName()}{$default}" . PHP_EOL;
}

echo "Rückgabetyp: " . ($ref->hasReturnType() ? $ref->getReturnType() : 'keiner') . PHP_EOL;
Funktion: berechnePreis Parameter: $float netto $float mwstSatz = 0.19 $bool runden = true Rückgabetyp: float

Dependency Injection: Konstruktor-Parameter automatisch auflösen

<?php
class Logger {
    public function __construct(private string $prefix = '[LOG]') {}
}

class UserService {
    public function __construct(private Logger $logger, private int $timeout = 30) {}
}

function autoWire(string $className): object {
    $refClass = new ReflectionClass($className);
    $constructor = $refClass->getConstructor();

    if ($constructor === null) {
        return new $className();
    }

    $args = [];
    foreach ($constructor->getParameters() as $param) {
        $type = $param->getType();
        if ($type instanceof ReflectionNamedType && !$type->isBuiltin()) {
            // Rekursiv instanziieren
            $args[] = autoWire($type->getName());
        } elseif ($param->isOptional()) {
            $args[] = $param->getDefaultValue();
        } else {
            throw new RuntimeException("Kann Parameter '{$param->getName()}' nicht auflösen.");
        }
    }

    return $refClass->newInstanceArgs($args);
}

$service = autoWire(UserService::class);
var_dump($service instanceof UserService); // bool(true)
bool(true)

Docblock und Metainformationen einer Methode lesen

<?php
class Rechner {
    /**
     * Addiert zwei Zahlen.
     *
     * @param int $a Erster Summand
     * @param int $b Zweiter Summand
     * @return int Die Summe
     */
    public function addiere(int $a, int $b): int {
        return $a + $b;
    }
}

$ref = new ReflectionMethod(Rechner::class, 'addiere');

echo "Datei:    " . $ref->getFileName() . PHP_EOL;
echo "Zeile:    " . $ref->getStartLine() . " – " . $ref->getEndLine() . PHP_EOL;
echo "Intern:   " . ($ref->isInternal() ? 'ja' : 'nein') . PHP_EOL;
echo "Variadic: " . ($ref->isVariadic() ? 'ja' : 'nein') . PHP_EOL;
echo "DocBlock:\n" . $ref->getDocComment() . PHP_EOL;
Datei: /path/to/script.php Zeile: 15 – 17 Intern: nein Variadic: nein DocBlock: /** * Addiert zwei Zahlen. * ... */

// Wichtig · Fallstricke

Nicht direkt instanziierbar: Der Versuch, new ReflectionFunctionAbstract() aufzurufen, führt zu einem Fatal Error, da die Klasse abstrakt ist. Verwende stattdessen ReflectionFunction oder ReflectionMethod.

Performance: Reflection-Operationen sind deutlich langsamer als direkte Aufrufe. In performance-kritischen Pfaden (z. B. in engen Schleifen) sollte das Ergebnis von Reflection-Analysen gecacht werden (z. B. in einem statischen Array oder einem DI-Container-Cache).

Closures: Closures können ebenfalls über ReflectionFunction inspiziert werden, das funktioniert genauso wie bei normalen Funktionen – alle Methoden von ReflectionFunctionAbstract stehen zur Verfügung.

PHP 8.0+: Seit PHP 8.0 unterstützt die Reflection-API Union-Typen (ReflectionUnionType) und Nullsafe-Typen; ab PHP 8.1 kommen Intersection-Typen (ReflectionIntersectionType) hinzu. Die Rückgabe von getReturnType() und getParameters()[n]->getType() kann daher komplexe Typ-Objekte zurückliefern.