Start · Sprachen · PHP · Referenz · Componere\Patch

Componere\Patch

Klasse

Ermöglicht das nachträgliche Ändern (Patchen) einer bestehenden PHP-Klasse zur Laufzeit, ohne deren ursprünglichen Quellcode zu verändern.

seit PHP 2.0.0 Kategorie: oop

Signatur

class Componere\Patch

Beschreibung

Componere\Patch ist Teil der Componere-Erweiterung und erlaubt es, eine bereits geladene Klasse zur Laufzeit zu modifizieren – d. h. neue Methoden hinzuzufügen oder bestehende zu überschreiben. Dies geschieht ohne Vererbung und ohne den ursprünglichen Quelltext anzufassen.

Ein typischer Anwendungsfall ist das nachträgliche Erweitern von Fremd- oder Framework-Klassen in Tests oder bei der Laufzeit-Instrumentierung (z. B. Logging, Mocking), ohne auf Subklassen oder Proxy-Objekte zurückgreifen zu müssen. Ein Patch wird auf eine konkrete Klasse angewendet und ist solange aktiv, bis er rückgängig gemacht wird oder das Objekt den Gültigkeitsbereich verlässt.

Im Unterschied zu Componere\Definition, die vollständig neue Klassen erzeugt, modifiziert Componere\Patch eine vorhandene Klasse direkt. Mit apply() wird der Patch aktiviert; alle danach erzeugten und bereits existierenden Instanzen der Zielklasse spiegeln die Änderungen sofort wider. Mit revert() lässt sich der ursprüngliche Zustand wiederherstellen.

Achtung: Die Componere-Erweiterung muss als PHP-Extension installiert sein (pecl install componere). Sie ist primär für Entwicklungs- und Testumgebungen gedacht; der Einsatz in Produktionssystemen erfordert sorgfältige Abwägung.

Parameter

Name Typ Default Beschreibung
$name Pflicht string Der vollqualifizierte Name der zu patchenden Klasse (z. B. 'MyNamespace\MyClass'). Die Klasse muss zum Zeitpunkt der Patch-Erstellung bereits geladen sein.
$interfaces array [] Optionales Array mit Namen von Interfaces, die die gepatchte Klasse nach der Aktivierung zusätzlich implementieren soll. Jedes Interface muss bereits geladen sein.

Rückgabewert

Typ

Beispiele

Methode einer bestehenden Klasse überschreiben

<?php
use Componere\Patch;
use Componere\Method;

class Logger {
    public function log(string $message): string {
        return 'ORIGINAL: ' . $message;
    }
}

$logger = new Logger();
echo $logger->log('Hallo') . PHP_EOL; // ORIGINAL: Hallo

// Patch erstellen und Methode überschreiben
$patch = new Patch(Logger::class);
$patch->addMethod('log', new Method(function(string $message): string {
    return 'PATCHED: ' . strtoupper($message);
}));

// Patch aktivieren
$patch->apply();

echo $logger->log('Hallo') . PHP_EOL; // PATCHED: HALLO

// Patch rückgängig machen
$patch->revert();

echo $logger->log('Hallo') . PHP_EOL; // ORIGINAL: Hallo
ORIGINAL: Hallo PATCHED: HALLO ORIGINAL: Hallo

Neue Methode hinzufügen und Interface implementieren

<?php
use Componere\Patch;
use Componere\Method;

interface Serializable2 {
    public function serialize2(): string;
}

class DataObject {
    public function __construct(private string $data) {}
    public function getData(): string { return $this->data; }
}

$obj = new DataObject('Testinhalt');

// Patch: neue Methode + Interface hinzufügen
$patch = new Patch(DataObject::class, [Serializable2::class]);
$patch->addMethod('serialize2', new Method(function(): string {
    return json_encode(['data' => $this->getData()]);
}));

$patch->apply();

echo $obj->serialize2() . PHP_EOL;
var_dump($obj instanceof Serializable2);

$patch->revert();
{"data":"Testinhalt"} bool(true)

// Wichtig · Fallstricke

Sichtbarkeit und Scope: Ein Patch-Objekt muss im Gültigkeitsbereich gehalten werden; wird es vom Garbage Collector eingesammelt, wird der Patch automatisch zurückgesetzt. Es empfiehlt sich daher, das Objekt explizit zu speichern.

  • apply() aktiviert den Patch; alle bestehenden und neuen Instanzen der Zielklasse sind sofort betroffen.
  • revert() macht den Patch rückgängig und stellt den Originalzustand wieder her.
  • Patches können nicht auf interne PHP-Klassen (z. B. stdClass, ArrayObject) angewendet werden.
  • Für Produktionssysteme ist diese Technik mit Vorsicht zu genießen, da sie das Laufzeitverhalten global verändert und zu schwer nachvollziehbaren Bugs führen kann.
  • Die Erweiterung ist nicht standardmäßig in PHP enthalten; sie muss separat über PECL installiert werden.