PHP:使用__call覆盖父方法

时间:2012-02-05 18:19:45

标签: php magic-methods dynamic-proxy

我想以某种方式隐藏父方法,以便为父类定义的方法调用子类的__call魔术方法。例如:

class C {
  function foo() { echo "foo\n"; }
}

class D extends C {
  function __call( $method, $args ) { echo "called $name\n"; }
}

$d = new D();
$d->foo();

// desired result: called foo
// actual result: foo

我已经检查过rename_function和override_function但这些方法不起作用。 ReflectionMethod有一个我尝试过的setAccessible方法,但是这似乎只有在你使用ReflectionMethod实例来调用方法时才有效。

后台:尝试使用可以利用PHP类型检查的RPC Proxy类。所以,如果我有一个RPCFoo,我可以使用类型提示或instanceof强制类型,以便我可以检查($ RPCFoo实例Foo)。

编辑:基类应该能够在不使用代理的情况下按原样使用。这样代理就可以成为系统配置的一部分,而不是代码。认为多个服务器都具有相同的代码库,但能够为每个服务器分配某些任务。如果本地服务器不处理请求的服务,则类加载器将返回代理而不是基类。如果本地服务器确实处理了请求的服务,它将返回基类。

再次编辑:提供的方法是可行的,但隐藏了IDE和反射的基类的设计界面。我试图使代理实现干净,以便只需从基类继承并实现代理接口。为了维护基类接口,代理开发人员必须重新实现所有公共和受保护的方法才能进行远程调用。然后,当在基类中更新某些内容时,也必须更新代理。最后,我想我只是想编写一个使用反射的代理生成器为开发人员做这个。

感谢您的回复!

3 个答案:

答案 0 :(得分:2)

您必须将foo方法的访问权限设置为private

class C {
    private function foo() {
        echo "foo\n";
    }
    public function __call($method, $args) {
        if(is_callable(array($this,$method))) {
            return call_user_func_array(array($this,$method), $args);
        } else {
            trigger_error("Call to undefined method '{$method}'");
        }
    }
}

答案 1 :(得分:0)

class C {

    public function __call($method, $args) {
        return call_user_func_array(array(__CLASS__ ,$method), $args);
    }

    protected function foo() { echo "foo<br />"; }
}

class D extends C {
    function __call( $method, $args ) { echo "called $method<br/>"; }
}

$d = new D();
$d->foo();

$c = new C();
$c->foo();

答案 2 :(得分:0)

我知道这个问题有点老了,但是我把它弄好了,所以我把它贴在这里以帮助遇到同样问题的人。

我的解决方案是使用magic __call()方法覆盖父方法:

public function foo($p1, $p2, $p3)
{
    if (get_class($this) == __CLASS__) {
        /* Do stuff here */
    } elseif (method_exists($this, '__call')) {
        return call_user_func_array([$this, '__call'], ['foo', func_get_args()]);
    }

    return false;
}

唯一的限制是父类本身不能有一个魔术__call()方法,否则它将从父类而不是扩展子类调用__call()方法。