How to call a closure that is a class variable?

Answer from StackOverflow

In PHP, methods and properties are in a separate namespace (you can have a method and a property with the same name), and whether you are accessing a property or a method depends of the syntax you are using to do so.

$expr->something() is a method call, so PHP will search for a method in the class.

$expr->something is a property fetch, so PHP will search for a property in the class.

$myInstance->lambda(); is parsed as a method call, so PHP searches for a method named lambda in your class, but there is no such method (hence the Call to undefined method error).

So you have to use the fetch property syntax to fetch the lambda, and then call it.

  • You can do this with ->lambda->__invoke():
$myInstance = new MyClass();
$myInstance->lambda->__invoke();

__invoke is one of PHP’s magic methods. When an object implements this method, it becomes invokable: it can be called using the $var() syntax. Anonymous functions are instances of Closure, which implements __invoke.
- Or assign it to a local variable:

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

Or call it using call_user_func:

call_user_func($myInstance->lambda);

call_user_func can call any callable, including anonymous functions.
Alternatively, if this is a common pattern in your code, you can setup a __call method to forward calls to your 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);
    }
}

Now this works:

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

Since PHP 5.4 you can even do that in a trait:

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();

Reference

http://stackoverflow.com/questions/7067536/how-to-call-a-closure-that-is-a-class-variable

發佈了72 篇原創文章 · 獲贊 14 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章