我是 PHP 新手,目前正在搞乱
array_reduce
,当我看到这种情况发生时:
php > echo array_reduce(array("(function($x){return $x;})"), function($p, $q) {return ($q)($p);}, "init");
Warning: Uncaught Error: Call to undefined function (function(, ){return ;})() in php shell code:1
Stack trace:
#0 [internal function]: {closure}('init', '(function(, ){r...')
#1 php shell code(1): array_reduce(Array, Object(Closure), 'init')
#2 {main}
thrown in php shell code on line 1
php > echo (function($x){return $x;})("init");
init
本质上,
array_reduce()
由三个部分组成——数组、reduce函数和初始值。这里我的reduce函数接受两个字符串func($x, $y)
并使用参数$y
- $x
调用return ($y)($x);
。所以我期望调用 array_reduce(array(a1, a2, a3), ..., "init")
,它将返回 a1(a2(a3("init")))
作为重复的函数调用。
因此,我还传入了一个匿名函数
(function($x){return $x;})
作为a1
,希望它能够正确调用并返回"init"
作为最终结果。事实上,当它单独运行时(参见第二个 php 命令),它会正确返回 "init"
。然而,当传递到array_reduce()
时,它不起作用。有人可以帮忙解释一下原因吗,最好用简单的语言解释一下?还有可能实现我想要的吗?
eval
的问题,如PHP文档中所述:
eval() 语言构造非常危险,因为它允许执行任意 PHP 代码。因此不鼓励使用它。如果您已仔细验证除了使用此构造之外没有其他选择,请特别注意不要在未事先正确验证的情况下将任何用户提供的数据传递到其中。
我建议您仅将
eval
用于已有的常量字符串。绝对不允许用户在没有经过显着清理的情况下向 eval
提供任意字符串;我建议即使这样,它也可能存在太大的安全漏洞。
如果您仍然希望继续使用
eval
,您可以执行以下操作:
<?php
$definitions = [
'(function($x){return "a1({$x})";})',
'(function($x){return "a2({$x})";})',
'(function($x){return "a3({$x})";})',
];
$functions = array_map(fn($f) => eval("return {$f};"), array_reverse($definitions));
$output = array_reduce($functions, fn($p, $q) => $q($p), 'init');
echo "{$output}\n";
这使用:
array_reverse
创建一个反向定义数组,因为函数将从内向外应用(即,没有它,输出将为 a3(a2(a1(init)))
)array_map
和 eval
将定义数组(作为字符串)映射到匿名函数