Start · Sprachen · PHP · Referenz · runkit7_method_redefine

runkit7_method_redefine

Funktion

Ändert den Code einer bestehenden Methode einer Klasse zur Laufzeit.

Kategorie: misc

Signatur

runkit7_method_redefine(string $classname, string $methodname, string|Closure $argument_list_or_closure, string $code = '', int $flags = RUNKIT7_ACC_PUBLIC, string $doc_comment = '', string $return_type = '', bool $is_strict = false): bool

Beschreibung

runkit7_method_redefine() ermöglicht es, den Quellcode (oder eine Closure) einer bereits definierten Methode einer Klasse während der Programmausführung auszutauschen. Dies ist nützlich in Test-Szenarien (z. B. beim Monkey-Patching), beim dynamischen Anpassen von Klassen, die nicht über normale Vererbung oder Dependency Injection überschrieben werden können, oder beim Experimentieren in Entwicklungsumgebungen.

Die Funktion gehört zur runkit7-PECL-Extension, die speziell für die Manipulation von Klassen, Methoden und Funktionen zur Laufzeit entwickelt wurde. Sie ersetzt das Ursprungs-runkit für PHP 7+. Der neue Methodenkörper kann entweder als PHP-Code-String oder als Closure übergeben werden.

Der Parameter $flags steuert die Sichtbarkeit (RUNKIT7_ACC_PUBLIC, RUNKIT7_ACC_PROTECTED, RUNKIT7_ACC_PRIVATE) sowie optional RUNKIT7_ACC_STATIC. Diese Konstanten können mit dem bitweisen OR-Operator (|) kombiniert werden.

Achtung: Diese Funktion sollte niemals in Produktivsystemen eingesetzt werden. Sie ist ausschließlich für Entwicklungs- und Testzwecke gedacht, da das Ändern von Methoden zur Laufzeit zu unvorhersehbarem Verhalten, Debugging-Schwierigkeiten und Sicherheitsrisiken führen kann.

Parameter

Name Typ Default Beschreibung
$classname Pflicht string Der Name der Klasse, deren Methode umdefiniert werden soll.
$methodname Pflicht string Der Name der Methode innerhalb der Klasse, die neu definiert werden soll.
$argument_list_or_closure Pflicht string|Closure Wird eine Closure übergeben, wird diese direkt als neuer Methodenkörper verwendet. Wird ein string übergeben, gilt dieser als Parameterliste (z. B. '$a, $b'), und der eigentliche Code wird über $code angegeben.
$code string Der PHP-Code-String für den Methodenkörper. Wird nur verwendet, wenn $argument_list_or_closure ein String ist.
$flags int RUNKIT7_ACC_PUBLIC Sichtbarkeits- und Typflags. Mögliche Werte: RUNKIT7_ACC_PUBLIC, RUNKIT7_ACC_PROTECTED, RUNKIT7_ACC_PRIVATE, RUNKIT7_ACC_STATIC. Können mit | kombiniert werden.
$doc_comment string Optionaler DocComment-String, der der neuen Methode zugewiesen wird.
$return_type string Optionale Typdeklaration für den Rückgabewert der neuen Methode (z. B. 'int' oder 'string').
$is_strict bool false Gibt an, ob die Methode im strikten Typmodus (declare(strict_types=1)) ausgeführt werden soll.

Rückgabewert

Typ
bool
Beschreibung
Gibt true bei Erfolg zurück, false bei einem Fehler (z. B. wenn die Methode nicht existiert oder die Klasse nicht gefunden wird).

Beispiele

Methode eines Objekts zur Laufzeit umdefinieren (String-Variante)

<?php
class Greeter {
    public function hello(): string {
        return 'Hallo Welt!';
    }
}

$obj = new Greeter();
echo $obj->hello() . PHP_EOL; // Ausgabe: Hallo Welt!

runkit7_method_redefine(
    'Greeter',
    'hello',
    '',
    'return "Guten Tag, PHP!";',
    RUNKIT7_ACC_PUBLIC
);

echo $obj->hello() . PHP_EOL; // Ausgabe: Guten Tag, PHP!
Hallo Welt! Guten Tag, PHP!

Methode mit einer Closure ersetzen (für Unit-Tests)

<?php
class PaymentService {
    public function charge(float $amount): string {
        // Echte Zahlungslogik ...
        return 'charged:' . $amount;
    }
}

// Im Testkontext: Methode durch Stub ersetzen
runkit7_method_redefine(
    'PaymentService',
    'charge',
    Closure::fromCallable(function(float $amount): string {
        return 'mocked:' . $amount;
    })
);

$svc = new PaymentService();
echo $svc->charge(49.99); // Ausgabe: mocked:49.99
mocked:49.99

// Wichtig · Fallstricke

Nur für Entwicklung und Tests: Der Einsatz von runkit7_method_redefine() in Produktivumgebungen ist gefährlich und wird ausdrücklich nicht empfohlen. Das nachträgliche Ändern von Methoden kann den opcode-Cache (z. B. OPcache) umgehen oder inkonsistente Zustände verursachen.

Die Funktion setzt voraus, dass die PECL-Extension runkit7 installiert und in der php.ini aktiviert ist (extension=runkit7). Außerdem muss runkit7.internal_override = On gesetzt sein, wenn interne PHP-Funktionen oder -Methoden überschrieben werden sollen.

Bei bestehenden Objektinstanzen wirkt sich die Umdefinierung sofort aus, da PHP Methoden zur Laufzeit über die Klassenstruktur auflöst. Eine Umdefinierung einer Methode in einem Elternteil hat keinen Einfluss auf Kindklassen, die die Methode bereits überschrieben haben.