-2

我正在用 PHP 编写一个 api。我有一个实现魔术功能的基类__call

class Controller
{
    public function __call($name, $arguments)
    {
        if(!method_exists($this,$name))
            return false;
        else if(!$arguments)
            return call_user_func(array($this,$name));
        else
            return call_user_func_array(array($this,$name),$array);
    }
}

和一个像这样的子类:

class Child extends Controller
{
    private function Test()
    {
        echo 'test called';
    }
}

所以当我这样做时:

$child = new Child();
$child->Test();

并加载页面需要很长时间,一段时间后 Web 浏览器会打印出无法请求该页面。php 没有输出,只有网络浏览器错误。

apache错误日志(仅最后一部分):

...
[Tue Sep 24 12:33:14.276867 2013] [mpm_winnt:notice] [pid 1600:tid 452] AH00418: Parent: Created child process 3928
[Tue Sep 24 12:33:15.198920 2013] [ssl:warn] [pid 3928:tid 464] AH01873: Init: Session Cache is not configured [hint: SSLSessionCache]
[Tue Sep 24 12:33:15.287925 2013] [mpm_winnt:notice] [pid 3928:tid 464] AH00354: Child: Starting 150 worker threads.
[Tue Sep 24 12:38:43.366426 2013] [mpm_winnt:notice] [pid 1600:tid 452] AH00428: Parent: child process exited with status 3221225725 -- Restarting.
[Tue Sep 24 12:38:43.522426 2013] [ssl:warn] [pid 1600:tid 452] AH01873: Init: Session Cache is not configured [hint: SSLSessionCache]

我找不到错误,但如果功能 Test 受到保护,一切正常。

找到的解决方案:

public function __call($name, $arguments)
{
    if(!method_exists($this,$name))
        return false;
    $meth = new ReflectionMethod($this,$name);
    $meth->setAccessible(true);
    if(!$arguments)
        return $meth->invoke($this);
    else
        return $meth->invokeArgs($this,$arguments);
}
4

2 回答 2

0

这种行为是文档中记录的一个问题(错误?)method_exists()即使method_exists()该方法是私有/受保护的,因此也无法从类外部访问,也返回 true。在您的情况下,这会导致无限递归,因为您的Child->Test()调用调用Child::__call(),它检查是否Test()存在(它确实存在,但不能被调用),然后尝试调用它,这再次导致__call()被调用。评论建议使用get_class_methods()可能会解决问题。我不确定为什么改变 to 的可见性Test()private改变你所说的行为。

于 2013-09-24T17:42:35.333 回答
0

Test()公众看到,它应该工作。

我不完全确定为什么私有可见性会导致 500 错误(而不是Call to private method...),但我怀疑这与涉及__call()函数的递归有关。PHP 中的一些特性弊大于利——你真的需要它吗?

于 2013-09-24T17:45:12.937 回答