PHP5.3:从类变量调用invoke时"调用未定义的方法"错误

lep*_*epe 6 php methods invoke

我一直在用__invoke魔术方法做一些测试(替换旧代码),我不确定这是不是一个bug:

让我们假设我们有一个班级:

class Calc {
    function __invoke($a,$b){
        return $a*$b;
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是可能的,并且没有任何问题:

$c = new Calc;
$k = $c;
echo $k(4,5); //outputs 20
Run Code Online (Sandbox Code Playgroud)

但是,如果我想要另一个类来存储该对象的实例,这不起作用:

class Test {
    public $k;
    function __construct() {
        $c = new Calc;
        $this->k = $c; //Just to show a similar situation than before
        // $this-k = new Calc; produces the same error.
    }
}
Run Code Online (Sandbox Code Playgroud)

当我们尝试调用它时会发生错误:

$t = new Test;
echo $t->k(4,5); //Error: Call to undefined method Test::k()
Run Code Online (Sandbox Code Playgroud)

我知道"解决方案"可能是在类Test(名为k)中使用call_user_func_array来"转发"调用,但这并不优雅.

我需要将该实例保留在公共类中(出于设计目的)并能够将其作为函数从其他类中调用...任何建议?

更新:

我找到了一些有趣的东西(至少对我而言):

如果我们将"类变量"分配给局部变量,它可以工作:

$t = new Test;
$m = $t->k;
echo $m(4,5);
Run Code Online (Sandbox Code Playgroud)

Sjo*_*erd 6

当你这样做时,PHP认为你想在实例$ t上调用方法k:

$t->k(4, 5)
Run Code Online (Sandbox Code Playgroud)

这是完全合理的.您可以使用中间变量来调用对象:

$b = $t->k;
$b(4, 5);
Run Code Online (Sandbox Code Playgroud)

另请参阅描述您的问题的错误#50029.


Gor*_*don 5

当你这样做时$test->k(),PHP认为你正在调用$test实例上的方法.由于没有命名的方法k(),PHP抛出异常.你要做的是让PHP返回公共属性k并调用它,但为此你必须首先分配k给一个变量.这是一个解除引用的问题.

您可以将魔术__call方法添加到您的Test类中,以检查是否存在具有被调用方法名称的属性,并调用该方法:

public function __call($method, $args) {
    if(property_exists($this, $method)) {
        $prop = $this->$method;
        return $prop();
    }
}
Run Code Online (Sandbox Code Playgroud)

我将调用的参数添加到您.您可能还想检查该属性is_callable.

但无论如何,那么你可以做到

$test->k();
Run Code Online (Sandbox Code Playgroud)