简体   繁体   English

如何在PHP中将函数转换为闭包?

[英]How to Convert a Function into a Closure in PHP?

I have function that uploads files to server: 我具有将文件上传到服务器的功能:

function upload() {

    $files = Input::file(self::$filename);

    foreach ($files as $key => $file) {
       // Validation
       // Uploading
    }
}

So, how to make this function as closure? 那么,如何使该函数作为闭包呢? That after loading it returns error or success information to output variable: 加载后将错误或成功信息返回到输出变量:

$results = function upload() {
}

In results should be result array of uploading files. results应该是上传文件的结果数组。 It can be error or success state. 它可以是错误或成功状态。

Updated and Expanded 更新和扩展

This answer addresses the OP's primary question of "How to Convert a Function into a Closure in PHP?" 该答案解决了OP的主要问题:“如何在PHP中将函数转换为闭包?” One way involves writing a nameless function and then assigning it to a variable. 一种方法涉及编写无名函数,然后将其分配给变量。 Since the OP's upload code is problematic, ie a method without a class, I therefore borrow the corrected code of @astax, modifying it for the purpose of illustrating the mechanics of how to create a closure in PHP, as follows: 由于OP的上传代码有问题,即没有类的方法,因此我借用了正确的@astax代码,对其进行了修改,以说明如何在PHP中创建闭包的机制,如下所示:

    <?php

    $f = function( $filename ) {

      $files = Input::file( $filename ); 

      foreach ($files as $key => $file) {
         // Validation
         // Uploading
      }

      return $arrResults;
    };

Note the trailing semicolon after the final brace. 注意最后一个括号后的尾部分号。 Also, the closure definition consists of an anonymous function. 另外,闭包定义由匿名函数组成。 You may get the result as follows: 您可能会得到如下结果:

<?php
$arrResults = $f( $filename );

 // or in a class:
$arrResults = $f( self::$filename );

Note: PHP does not have named closures, so the function needs to be anonymous. 注意:PHP没有命名闭包,因此该函数需要匿名。 Usually it is assigned to a variable but PHP 7 provides more flexibility such that you may avoid setting a variable as the following two basic examples indicate: 通常,它被分配给变量,但是PHP 7提供了更大的灵活性,因此您可以避免设置变量,如以下两个基本示例所示:

<?php

echo (function() {
      return 2 * 2;
     })(),"\n",


(function(){
         return function(){
           return 3 * 3;
         };
})()();

See live code . 查看实时代码

This syntax is possible thanks to the support for function call chaining in PHP 7. 由于PHP 7支持函数调用链接,因此可以使用此语法。

Note: if your code includes a return statement, when the closure executes , you may assign the return value to a variable. 注意:如果您的代码包含return语句,则在执行闭包时 ,可以将返回值分配给变量。

Incidentally, two useful articles on PHP's closures: see this issue as well in this issue . 顺便说一句,有关PHP的闭包的两篇有用的文章:在本期中也同时看到此问题

Lastly, note while other languages recognize a bound variable with a function as a closure and a nameless function as an anonymous function, in PHP support for each is done vis a vis the Closure class . 最后,请注意,尽管其他语言将绑定变量识别为函数,将其作为闭包,将无名函数作为匿名函数,但在PHP中,每种支持都是通过Closure类实现的

Caveat: 警告:

Care should be taken when creating a closure from the Closure object's fromCallable method since it evidently yields a more restricted closure as the following code demonstrates: 从Closure对象的fromCallable方法创建闭包时应小心,因为它显然会产生更受限制的闭包,如以下代码所示:

<?php
class A {
    private $name;
    public function __construct($name)
    {
        $this->name = $name;
    }
}

$person = new A("Tim");

function test() {
    return $this->name;
}

$f = function() {
    return $this->name;
};
$cl = Closure::fromCallable( $f );
echo $cl->bindTo($person, 'A')();

echo "\n\nBut, Closure::fromCallable problematic:\n";

try {
  $cl = Closure::fromCallable( "test" );
  echo $cl->bindTo($person, 'A')();
} catch (Error $e) {
   echo "Unable to bind closure from callable because: \n";
   echo $e->getMessage();
}

see live code 查看实时代码

The error message that results is as follows: 结果错误消息如下:

Warning: Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure() in /in/qso7b on line 26 Unable to bind closure from callable because: Function name must be a string 警告:在第26行的/ in / qso7b中,无法重新绑定由ReflectionFunctionAbstract :: getClosure()在/ in / qso7b中创建的闭包范围无法将闭包与可调用绑定,因为:函数名称必须是字符串

Since you're using self:: I assume you expect to run this function from inside a class. 由于您使用的是self::我假设您希望从类内部运行此函数。 But you can't really do this - the function should be defined in the class to be able to use self:: . 但是您实际上不能做到这一点-应该在类中定义函数才能使用self::

But really, you can just pass it as a parameter. 但实际上,您可以将其作为参数传递。

function upload($filename) {

    $files = Input::file($filename); // note, self:: removed

    foreach ($files as $key => $file) {
       // Validation
       // Uploading
    }

    return $result;
}

And when you need to use it inside your class, call it this way: 当您需要在班级内部使用它时,可以这样调用:

$result = upload(self::$filename);

For Converting a Function into a Closure in PHP, you can : 为了在PHP中将函数转换为闭包,您可以:

Since PHP 7 >= 7.1.0, you can use Closure::fromCallable() 由于PHP 7> = 7.1.0,因此可以使用Closure :: fromCallable()

$cl = Closure::fromCallable("upload");
$result = $cl();

Before (PHP >= 5.4.0), you can use ReflectionFunction::getClosure() 之前(PHP> = 5.4.0),可以使用ReflectionFunction :: getClosure()

$reflexion = new ReflectionFunction('upload');
$cl = $reflexion->getClosure();
$result = $cl();

Another idea is to construct a new function that call your main function : 另一个想法是构造一个新函数来调用您的main函数:

$cl = function (...$args) {
    return upload(...$args);
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM