一尘不染

如何调用作为类变量的闭包?

php

class MyClass {
  var $lambda;
  function __construct() {
    $this->lambda = function() {echo 'hello world';};
    // no errors here, so I assume that this is legal
  }
}

$myInstance = new MyClass();
$myInstance->lambda();
//Fatal error: Call to undefined method MyClass::lambda()

那么到达类变量的正确语法是什么?


阅读 242

收藏
2020-05-29

共1个答案

一尘不染

在PHP中,方法和属性位于单独的命名空间中(您可以具有相同名称的方法和属性),而访问属性还是方法取决于您使用的语法。

$expr->something()是一个方法调用,因此PHP将something在类的方法列表中进行搜索。

$expr->something是属性提取,因此PHP将something在类的属性列表中搜索。

$myInstance->lambda();被解析为方法调用,因此PHP会lambda在您的类中搜索一个命名的方法,但是没有这样的方法(因此
Call to undefined method error)。

因此,您必须使用 fetch属性 语法来获取lambda,然后对其进行调用。

  • 从PHP 7.0开始,您可以使用($obj->lambda)()
    ($obj->lambda)();
    

括号确保PHP解析($obj->lambda)获取名为lambda的属性 。然后,()调用获取属性的结果。

  • 或者,您可以使用以下方法->lambda->__invoke()
    $myInstance = new MyClass();
    

    $myInstance->lambda->__invoke();

__invokePHP的魔术方法之一。当对象实现此方法时,它可以调用:可以使用$var()语法来调用它。匿名功能的实例Closure,其实现__invoke

  • 或将其分配给局部变量:

    $lambda = $myInstance->lambda;
    

    $lambda();

  • 或使用call_user_func调用它:

    call_user_func($myInstance->lambda);
    

call_user_func可以调用任何callable,包括匿名函数。

  • 或者,如果这是代码中的常见模式,则可以设置一种__call方法来将调用转发到lambda:
    class MyClass
    

    {
    private $lambda;

    public function __construct()
    {
        $this->lambda = function() {
            echo "Hello world!\n";
        };
    }
    
    public function __call($name, $args)
    {
        return call_user_func_array($this->$name, $args);
    }
    

    }

现在这有效:

    $myInstance = new MyClass();
$myInstance->lambda();

从PHP 5.4开始,您甚至可以在特征中做到这一点:

    trait LambdasAsMethods
{
    public function __call($name, $args)
    {
        return call_user_func_array($this->$name, $args);
    }
}

class MyClass
{
    use LambdasAsMethods;

    private $lambda;

    public function __construct()
    {
        $this->lambda = function() {
            echo "Hello World!\n";
        };
    }
}

$myInstance = new MyClass();
$myInstance->lambda();
2020-05-29