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

时间:2017-09-17 18:17:46

标签: php

我有将文件上传到服务器的功能:

function upload() {

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

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

那么,如何使这个函数成为闭包?加载后,它会将错误或成功信息返回到输出变量:

$results = function upload() {
}

results中应该是上传文件的结果数组。它可能是错误或成功状态。

3 个答案:

答案 0 :(得分:2)

由于您正在使用self::,我假设您希望从类中运行此函数。但是你不能真正做到这一点 - 应该在类中定义函数以便能够使用self::

但实际上,您可以将其作为参数传递。

function upload($filename) {

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

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

    return $result;
}

当你需要在课堂上使用它时,请按照这样的方式调用它:

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

答案 1 :(得分:1)

更新并扩展

这个答案解决了OP的主要问题"如何在PHP中将函数转换为闭包?"一种方法是编写无名函数,然后将其赋值给变量。由于OP的上传代码是有问题的,即没有类的方法,因此我借用了@astax的更正代码,修改它是为了说明如何在PHP中创建闭包的机制,如下所示:

    <?php

    $f = function( $filename ) {

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

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

      return $arrResults;
    };

注意最后一个括号后面的尾随分号。此外,闭包定义包含匿名函数。您可以按如下方式获得结果:

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

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

注意:PHP没有命名闭包,因此该函数需要是匿名的。通常将它分配给变量,但PHP 7提供了更大的灵活性,以便您可以避免设置变量,如以下两个基本示例所示:

<?php

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


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

请参阅live code

由于PHP 7中对函数调用链的支持,这种语法是可行的。

注意:如果您的代码包含一个return语句,当闭包执行时,您可以将返回值赋给变量。

顺便提一下,关于PHP关闭的两篇有用的文章:请参阅此issue以及此issue

最后,请注意,当其他语言识别绑定变量时,函数作为闭包,无名函数作为匿名函数,在PHP中,每个语言都支持Closure class

警告:

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

请参阅live code

结果的错误消息如下:

  

警告:无法重新绑定创建的闭包范围   第26行/ in / qso7b中的ReflectionFunctionAbstract :: getClosure()   无法绑定来自callable的闭包,因为:函数名必须是a   串

答案 2 :(得分:0)

要在PHP中将函数转换为闭包,您可以:

由于PHP 7&gt; = 7.1.0,您可以使用Closure::fromCallable()

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

之前(PHP&gt; = 5.4.0),您可以使用ReflectionFunction::getClosure()

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

另一个想法是构建一个调用主函数的新函数:

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