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"
Antworten
Zu viele Anzeigen?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.
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.