[英]PHP5.3: “Call to undefined method” error when calling invoke from class variable
我一直在使用__invoke magic方法进行一些测试(以替换旧代码),但我不确定这是否是错误:
假设我们有一个类:
class Calc {
function __invoke($a,$b){
return $a*$b;
}
}
以下是可能的,并且可以正常工作:
$c = new Calc;
$k = $c;
echo $k(4,5); //outputs 20
但是,如果我想让另一个类存储该对象的实例,则无法正常工作:
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.
}
}
当我们尝试像这样调用时会发生错误:
$t = new Test;
echo $t->k(4,5); //Error: Call to undefined method Test::k()
我知道“解决方案”可能是在Test类(名为k)中具有一个函数,以使用call_user_func_array“转发”调用,但这并不优雅。
我需要将该实例保留在一个公共类中(出于设计目的),并能够从其他类中将其作为函数调用...有什么建议吗?
更新:
我发现了一些有趣的东西(至少出于我的目的):
如果我们将“类变量”分配给局部变量,它将起作用:
$t = new Test;
$m = $t->k;
echo $m(4,5);
PHP认为您要在实例$ t上调用方法k:
$t->k(4, 5)
这是完全合理的。 您可以使用中间变量来调用对象:
$b = $t->k;
$b(4, 5);
另请参见错误#50029 ,它描述了您的问题。
当您执行$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();
}
}
我将在调用中添加参数。 您可能还需要检查属性是否为is_callable
。
但是无论如何,你可以做
$test->k();
您不能使用方法语法(例如$ foo-> bar())来通过__invoke调用闭包或对象,因为引擎始终认为这是方法调用。 您可以通过__call模拟它:
function __call($name, $params) {
if(is_callable($this->$name)) {
call_user_func_array($this->$name, $params);
}
}
但它不能按原样工作。
如果您调用$ test-> k(),PHP将在$ test实例上搜索一个名为“ k”的方法,显然它将引发Exception。
要解决此问题,您可以创建属性“ k”的吸气剂
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.
}
public function getK() {
return $this->k;
}
}
因此,现在您可以按以下方式使用函子:
$t = new Test();
echo $t->getK()(4,5);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.