PHP5.3:“调用未定义的方法”从类变量调用 invoke 时出错
我一直在用 __invoke 魔术方法进行一些测试(以替换旧代码),我不确定这是否是一个错误:
让我们假设我们有一个类:
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);
I have been doing some tests (to replace old code) with the __invoke magic method and I'm not sure this is a bug or not:
Lets suppose we have a class:
class Calc {
function __invoke($a,$b){
return $a*$b;
}
}
The following is possible and works without any problem:
$c = new Calc;
$k = $c;
echo $k(4,5); //outputs 20
However if I want to have another class to store an instance of that object,
this doesn't work:
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.
}
}
The error occurs when we try to call it like:
$t = new Test;
echo $t->k(4,5); //Error: Call to undefined method Test::k()
I know that a "solution" could be to have a function inside the class Test (named k) to "forward" the call using call_user_func_array but that is not elegant.
I need to keep that instance inside a common class (for design purposes) and be able to call it as function from other classes... any suggestion?
Update:
I found something interesting (at least for my purposes):
If we assign the "class variable" into a local variable it works:
$t = new Test;
$m = $t->k;
echo $m(4,5);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
当您这样做时,PHP 认为您想在实例 $t 上调用方法 k:
这是完全合理的。您可以使用中间变量来调用对象:
另请参阅 bug #50029,这描述了您的问题。
PHP thinks you want to call a method k on instance $t when you do:
which is perfectly reasonable. You can use an intermediate variable to call the object:
See also bug #50029, which describes your issue.
当您执行
$test->k()
时,PHP 认为您正在调用$test
实例上的方法。由于没有名为k()
的方法,PHP 会抛出异常。您想要做的是让 PHP 返回公共属性k
并调用它,但要做到这一点,您必须首先将k
分配给变量。这是一个取消引用的问题。您可以将神奇的
__call
方法添加到您的Test
类中,以检查是否存在具有被调用方法名称的属性,然后调用它:我将参数添加到对你的召唤。
您可能还想检查属性
is_callable
。但无论如何,你可以这样做
When you do
$test->k()
, PHP thinks you are calling a method on the$test
instance. Since there is no method namedk()
, PHP throws an exception. What you are trying to do is make PHP return the public propertyk
and invoke that, but to do so you have to assignk
to a variable first. It's a matter of dereferencing.You could add the magic
__call
method to yourTest
class to check if there is a property with the called method name and invoke that instead though:I leave adding the arguments to the invocation to you.
You might also want to check if the property
is_callable
.But anyway, then you can do
您不能使用方法语法(如 $foo->bar() )来调用闭包或带有 __invoke 的对象,因为引擎始终认为这是一个方法调用。您可以通过 __call: 模拟它,
但它不会按原样工作。
You can not use method syntax (like $foo->bar() ) to call closures or objects with __invoke, since the engine always thinks this is a method call. You could simulate it through __call:
but it would not work as-is.
如果你调用 $test->k() PHP 将在 $test 实例上搜索名为“k”的方法,显然它会抛出异常。
为了解决这个问题,你可以创建属性“k”的 getter
所以现在你可以这样使用函子:
If you call $test->k() PHP will search for a method called "k" on the $test instance and obviously it will throws an Exception.
To resolve this problem you can create a getter of the property "k"
So now you can use the functor in this way: