是否可以在PHP 5.2.x中模拟闭包而不使用全局变量?

aef*_*fxx 9 php closures global-variables simulate

是否可以在PHP 5.2.x中模拟闭包而不使用全局变量?我可以想到一种将所需变量作为额外参数传递给闭包的方法,但这并不是最佳实践.

有任何想法吗?

Gor*_*don 7

有趣的问题.我说这根本不可能,但让我们看看

引用IBM - PHP5.3中的新功能,第2部分

闭包是一个在自己的环境中计算的函数,它有一个或多个绑定变量,可以在调用函数时访问它们.

进一步(强调我的)

要从外部环境导入的变量在闭包函数定义的use子句中指定.默认情况下,它们按值传递,这意味着如果我们更新闭包函数定义中传递的值,它将不会更新外部值.

使用global将通过引用传递,虽然可以通过&use子句中使用闭包来通过引用绑定变量,但它已经偏离5.3默认行为.

$var = 'yes';
$fn  = create_function('', 'global $var; $var = "no";');
$fn();
echo $var; // outputs no
Run Code Online (Sandbox Code Playgroud)

您可以复制全局变量,以便按值使用它,例如

$var = 'yes';
$fn  = create_function('', 'global $var; $tmp = $var; $tmp = "no";');
$fn();
echo $var; // outputs yes
Run Code Online (Sandbox Code Playgroud)

此外,在create_function创建函数时但在运行函数时,不会计算(绑定)全局变量的值(使用时)

$var = 'yes';
$fn  = create_function('', 'global $var; $tmp = $var; return $tmp;');
$var = 'maybe';
echo $fn(); // outputs maybe

$var = 'yes';
$fn  = function() use ($var) { return $var; };
$var = 'maybe';
echo $fn(); // outputs yes
Run Code Online (Sandbox Code Playgroud)

同样重要的是

在对象中定义时,一个方便的事情是闭包通过$ this变量可以完全访问对象,而无需显式导入它.*虽然我认为这在最终的PHP5.3中被删除了

对于global关键字,这是不可能的,您也不能只使用$this.在定义函数体时,无法从类中引用属性create_function.

class A {

    protected $prop = 'it works';

    public function test()
    {
        $fn = create_function('', 'echo $this->prop;');
        return $fn;
    }
}

$a = new A;
$fn = $a->test();
$fn();
Run Code Online (Sandbox Code Playgroud)

会导致

Fatal error: Using $this when not in object context
Run Code Online (Sandbox Code Playgroud)

总结一下
虽然您可以创建一个从全局范围导入变量的函数,但您不能使用另一个范围中的变量创建一个函数.并且因为你在使用create_function时在技术上没有绑定,但在执行创建的函数时导入,我想说这个限制使得闭包成为一个lambda.


编辑:下面的Onno Marsman提供的解决方案虽然相当不错.它没有完全模拟Closures,但实现非常接近.

  • 没有任何词语可以描述这是多么可怕.(不是你的答案.) (2认同)