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

发布于 2024-11-29 12:54:56 字数 338 浏览 1 评论 0原文

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

那么访问类变量的正确语法是什么?

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

So what is the correct syntax for reaching class variables ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

许你一世情深 2024-12-06 12:54:56

在 PHP 中,方法和属性位于单独的命名空间中(您可以拥有同名的方法和属性),并且是否访问属性或方法取决于您所使用的语法。

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

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

$myInstance->lambda(); 被解析为方法调用,因此 PHP 在您的类中搜索名为 lambda 的方法,但没有这样的方法(因此调用未定义的方法错误)。

因此,您必须使用 fetch property 语法来获取 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 可以调用任何 call_user_func php.net/manual/en/language.types.callable.php" rel="noreferrer">可调用,包括匿名函数。

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

    类 MyClass
    {
        私有$lambda;
    
        公共函数 __construct()
        {
            $this->lambda = 函数() {
                echo "你好世界!\n";
            };
        }
    
        公共函数 __call($name, $args)
        {
            返回 call_user_func_array($this->$name, $args);
        }
    }
    

    现在可以了:

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

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

    特征 LambdasAsMethods
    {
        公共函数 __call($name, $args)
        {
            返回 call_user_func_array($this->$name, $args);
        }
    }
    
    我的班级
    {
        使用 LambdasAsMethods;
    
        私有$lambda;
    
        公共函数 __construct()
        {
            $this->lambda = 函数() {
                echo "你好世界!\n";
            };
        }
    }
    
    $myInstance = new MyClass();
    $myInstance->lambda();
    

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 something in the class' list of methods.

$expr->something is a property fetch, so PHP will search something in the class' list of properties.

$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.

  • Since PHP 7.0, you can do this with ($obj->lambda)():

    ($obj->lambda)();
    

    The parentheses make sure that PHP parses ($obj->lambda) as fetch the property named lambda. Then, () calls the result of fetching the property.

  • or 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();
    
π浅易 2024-12-06 12:54:56

您还可以使用 ReflectionFunction 调用 lambda 函数,而无需更改类中的某些内容。

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

或者如果你必须传递参数那么

$args = array('arg'=>'value');
$lambda->invokeArgs($args);

You can also call your lambda function without change something in your class, using ReflectionFunction.

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

or if you have to pass arguments then

$args = array('arg'=>'value');
$lambda->invokeArgs($args);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文