3 Stimmen

PHP ReflectionClass hasMethod und __call()

Ich erstelle eine dynamische Klasse, die auf die magische __call() Methode reagiert. Das Problem ist, da ich dies auf Basis eines bereits vorhandenen Frameworks (Kohana) baue, überprüft es, ob die Methode der Klasse mit ReflectionClass::hasMethod existiert, und es scheint nicht die __call() magische Methode zum Überprüfen ihres Vorhandenseins auszulösen. Was könnte ich in diesem Fall tun? Es scheint, als ob, wenn du die Methode dynamisch hinzufügst (wie $this->{$name} = function(){}), kann es sie trotzdem nicht "sehen"

2voto

Dan Lugg Punkte 19356

Ohne weitere Details bin ich mir nicht sicher, ob das ausreicht, aber Sie könnten eine Proxy-Klasse erstellen, um eine Zwischenfunktionalität auszuführen:

   class MyProxy {

    protected $_object  = null;
    protected $_methods = array();

    public function __construct($object) {
        if (!is_object($object)) {
            throw new InvalidArgumentException('$object muss ein Objekt sein');
        }
        $this->_object = $object;
    }

    public function __call($name, $arguments) {
        return $this->callMethod($name, $arguments);
    }

    public function setMethod($name, Closure $method) {
        $this->_methods[(string) $name] = $method;
    }

    public function callMethod($name, array $arguments) {
        if (isset($this->_methods[$name])) {
            return call_user_func_array($this->_methods[$name], $arguments);
        }
        return call_user_func_array(array($this->_object, $name), $arguments);
    }

}

Indem Sie $proxy->setMethod('foo', function () { }); aufrufen, können Sie dynamisch Methoden an das Objekt "anheften". Wenn Sie $proxy->foo() aufrufen, wird zuerst gegen die dynamisch angefügten Methoden gesucht; wenn eine gefunden wird, wird sie aufgerufen. Andernfalls wird sie einfach zum internen Objekt delegiert.

Das Problem bei diesem Ansatz ist jedoch, dass angefügte Methoden nicht an den Proxy gebunden sind. Mit anderen Worten, $this existiert nicht im Bereich einer angefügten Methode.

Dies kann jedoch mit Funktionen ab PHP 5.4 behoben werden.

public function setMethod($name, Closure $method) {
    $this->_methods[(string) $name] = Closure::bind($method, $this);
}

Wir haben setMethod verbessert, um die übergebene Closure an den Proxy zu binden. Jetzt wird im Bereich einer angefügten Methode $this auf das Proxy-Objekt zeigen.

Wir hätten es an das eingeschlossene Objekt binden können, aber dann könnten die angefügten Methoden nicht mit dem Proxy kommunizieren (oder anderen angefügten Methoden). Zur Vollständigkeit sollten Sie __get und __set Magie hinzufügen, um den Zugriff auf Eigenschaften an das interne Objekt weiterzuleiten (oder sie im Proxy behandeln, was auch immer)

Außerdem weiß das interne Objekt nichts über den Proxy, also kennen seine Methoden (aus der Klassendefinition) keine dieser dynamischen Magie sowieso nicht.

1voto

Charles Punkte 49941

Scheint so, als ob, wenn Sie die Methode dynamisch hinzufügen (wie $this->{$name} = function(){}), kann sie es immer noch nicht "sehen"

Richtig, da Sie eine neue Eigenschaft erstellen, nicht eine Methode. Zum Zeitpunkt des Schreibens unterstützte PHP das Aufrufen anonymer Funktionen in Eigenschaften ohne Verwendung von __call nicht, was nicht Reflection-freundlich ist. Eigenschaften mit anonymen Funktionen als Methoden funktionieren korrekt in PHP 5.4.

Der einzige andere Weg, eine Methode zu einer Klasse hinzuzufügen, sodass Reflection darauf zugreifen kann, ist die Verwendung der hoch experimentellen "runkit" Erweiterung.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X