为什么匿名函数似乎在此PHP对象中被拒绝

时间:2017-07-25 01:54:30

标签: php closures anonymous-function

我目前正在搞乱PHP,我注意到一些我个人没有注意到的有趣内容。匿名函数似乎不在对象内部工作。为什么呢?

示例:

$loop = function ($do) {
    $i = 2;
    $do((object) [
        "i" => $i,
        "domore" => (function () {
            echo "hi";
        })
    ]);
};

$loop(function ($data) {
   echo $data->i;
   echo $data->domore();
});

引发错误:

2<br />
<b>Fatal error</b>:  Uncaught Error: Call to undefined method stdClass::delay() in [...][...]:16
Stack trace:
#0 [...][...](10): {closure}(Object(stdClass))
#1 [...][...](17): {closure}(Object(Closure))
#2 {main}
  thrown in <b>[...][...]</b> on line <b>16</b><br />

同样,返回数据的相同代码是数组而不是对象:

$loop = function ($do) {
    $i = 2;
    $do([
        "i" => $i,
        "domore" => function () {
            echo "hi";
        }
    ]);
};

$loop(function ($data) {
   echo $data["i"];
   echo $data["domore"]();
});

只需按预期返回2hi即可。这对我来说似乎是一种奇怪的行为(来自javascript的人)所以我会感谢某种理由。请注意,此代码不具有实际用途,因此优良或不良的实践对此没有任何影响。想想教育。

编辑: Laravel完全符合我的要求,这让我觉得这不是不可能,但我只是在PHP中错误地实现了它:

DB::table('users')
    ->join('contacts', function ($join) {
        $join->on('users.id', '=', 'contacts.user_id')->orOn(...);
    })->get();

1 个答案:

答案 0 :(得分:3)

匿名函数在对象中工作正常。你得到了这个错误,因为domore不是一个方法而你正在调用它,它是一个恰好是闭包的属性。为了区分您在寻址属性时需要使用括号,例如:

$loop(function ($data) {
   echo $data->i;
   echo ($data->domore)();
});

输出:

2hi

为什么这是必要的,因为方法和属性存在于不同的符号表中,这意味着你可以拥有一个属性和一个同名的方法(请不要这样做)你需要知道哪个正在解决。 E.g:

$foo = new class
{
    public $func;

    public function __construct()
    {
        $this->func = function () {
            echo "foo";
        };
    }

    public function func()
    {
        echo "bar";
    }
};

($foo->func)();
$foo->func();

输出:

foobar