PHP ReflectionClass hasMethod and __call()



我正在创建一个响应魔术__call()方法的动态类。问题是,因为我是在已经存在的框架(Kohana)之上构建这个,它检查类的方法是否使用ReflectionClass::hasMethod存在,并且它似乎不会触发__call()魔术方法来检查它的存在。在这种情况下我能做什么?似乎如果您动态添加方法(如$this->{$name} = function(){}),它仍然无法"看到"它

如果没有更多的细节,我不确定这是否足够,但是您可以创建代理类来执行中间功能:

   class MyProxy {
    protected $_object  = null;
    protected $_methods = array();
    public function __construct($object) {
        if (!is_object($object)) {
            throw new InvalidArgumentException('$object must be an object');
        }
        $this->_object = $object;
    }
    public function __call($name, $arguments) {
        return $this->callMethod($name, $arguments);
    }
    public function setMethod($name, Closure $method) {
        $this->_methods[(string) $key] = $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);
    }
}

通过调用$proxy->setMethod('foo', function () { });,您可以动态地将方法"附加"到对象上。当你调用$proxy->foo()时,它首先会对动态附加的方法进行查找;如果它找到了,就会给它打电话。否则,它就会委托给内部对象。

现在,这种方法的问题是附加的方法没有绑定到代理。换句话说,$this不存在于附加方法的作用域中。

这个可以通过PHP 5.4+的特性来修复。

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

我们改进了setMethod,将传递的闭包重新绑定到代理。现在,在附加方法的作用域中,$this将指向代理对象。

我们可以将其反弹到封闭的对象,但随后附加的方法无法与代理(或其他附加方法)通信。为了完整起见,您需要添加__get__set魔术,以转发对内部对象的属性访问/改变调用(或在代理中处理它们,无论)

此外,内部对象对代理没有任何线索,所以它的方法(来自类定义的)无论如何都不会知道任何动态魔术。

似乎如果你动态添加方法(如$this->{$name} = function(){})),它仍然无法"看到"它

对,当你创建一个新的属性,而不是一个方法。在撰写本文时,PHP不支持在不经过__call的情况下调用属性中的匿名函数,这是不支持反射的。property -with- anonymousfunctions -as-method在PHP 5.4中正常工作

在类中添加方法的唯一方法是使用高度实验性的"runkit"扩展。

相关内容

  • 没有找到相关文章

最新更新