无法在php

时间:2019-01-27 22:26:58

标签: php closures

我试图使用闭包编写类似js的php。但是,我不明白为什么不能将闭包分配给stdClass属性。

代码说明了自己

$sum = function ($a, $b) {return $a + $b;};
echo $sum(11, 11);
// prints 22



$arr = [];
$arr['sum'] = function ($a, $b) {return $a + $b;};
echo $arr['sum'](22, 22);
// prints 44



$cl = new stdClass;
$cl->sum = function ($a, $b) {return $a + $b;};
echo $cl->sum(33, 33);
// Fatal error: Uncaught Error: Call to undefined method stdClass::sum()



# although I can't think of any use cases for this
class Custom {
    public $sum = NULL;

    function __construc() {
        $this->sum = function ($a, $b) {return $a + $b;};
    }
}

$custom = new Custom;
echo $custom->sum(44, 44);
// Fatal error: Uncaught Error: Call to undefined method Custom::sum()

2 个答案:

答案 0 :(得分:0)

只需将属性名称括在方括号中即可。

echo ($cl->sum)(33, 33);
echo ($custom->sum)(44, 44);

3v4l中的示例:

https://3v4l.org/3ZqNV

根据评论进行编辑:

Javascript中的对象只能具有属性。该属性可以是原始值,其他对象或函数,但是该属性的名称尽管具有内容,但还是唯一的。

在PHP中,对象可以同时具有属性和方法。

假设我们有以下代码:

class MyClass 
{

    public $foo;

    public function __construct() 
    {
        $this->foo = function(int $a, int $b): int {
            return $a * $b;
        };
    }

    public function foo(int $a, int $b): int 
    {
        return $a + $b;
    }
}

$myClass = new MyClass();

echo $myClass->foo(2, 3);

属性foo和方法foo都具有相同的签名,但是程序员的意愿是什么?

此代码将调用方法foo并显示5,因此任何行$var->name()都被解释为方法调用。

如果要在属性内部调用闭包,则必须使用其他语法,以免产生歧义。

echo ($myClass->foo)(2, 3) //Prints 6

https://3v4l.org/PXiMQ

答案 1 :(得分:0)

您可以使用闭包方法bind()bindTo()call()

$cl = new stdClass;
$sum = function ($a, $b) {return $a + $b;};
Closure::bind($sum, $cl);

echo $sum(33, 33); // this function is now part of the class. 

如果希望扩展此功能,则可以在类中创建一个注册函数,该函数依赖于__call()之类的魔术方法来检查该方法是否存在,如果存在,请在内部调用此方法。 / p>