PHP 7.2-在字符串中包含函数体时如何动态创建匿名函数

时间:2018-09-30 15:03:42

标签: php anonymous-function php-7.2

当字符串中包含函数体时,如何动态创建匿名函数。

例如

$user = "John Doe";
$body = "echo 'Hello' . $user;";

$myFunct = function($user) {$body}; // How do I have function body here from string.

$myFunct($user);

任何帮助将不胜感激。

P.S。 我正在寻找PHP早期版本中存在的create_function()功能的替代品。就像在create_function()中,我们可以将函数体作为字符串传递一样,我想从字符串变量中定义匿名函数的体。

6 个答案:

答案 0 :(得分:16)

如果您已经探索了所有其他选项,并且绝对确定实现目标的唯一方法是使用字符串中的代码在运行时定义自定义函数,则有两种选择使用create_function

快速的解决方案是只使用eval

function create_custom_function($arguments, $body) {
    return eval("return function($arguments) { $body };");
}

$myFunct = create_custom_function('$user', 'echo "Hello " . $user;');

$myFunct('John Doe');
// Hello John Doe

但是,可以禁用eval()。如果即使在eval不可用的服务器上也需要这种功能,则可以使用穷人的评估方法:将功能写入临时文件,然后将其包括在内:

function create_custom_function($arguments, $body) {
    $tmp_file = tempnam(sys_get_temp_dir(), "ccf");
    file_put_contents($tmp_file, "<?php return function($arguments) { $body };");
    $function = include($tmp_file);
    unlink($tmp_file);

    return $function;
}

$myFunct = create_custom_function('$user', 'echo "Hello " . $user;');

$myFunct('John Doe');
// Hello John Doe

但是,老实说,我强烈建议您反对这些方法,并建议您找到其他实现目标的方法。如果要构建自定义代码混淆器,则最好创建一个PHP扩展,在执行之前先对代码进行混淆处理,这与ionCube Loader和Zend Guard Loader的工作原理类似。 < / p>

答案 1 :(得分:2)

您可以使用可调用类型提示。这是一个例子

function callThatAnonFunction(callable $callback) {
    return $callback();
}

它可以使用带有任何arg参数的匿名函数:

$user = "person";
$location = "world";
callThatAnonFunction(function() use ($user, $location) {
    echo "Hello " . $user . " in " . $location;
});

答案 2 :(得分:2)

您可以尝试以下方法:

$user = "John Doe";
$body = "echo 'Hello' . $user;";

$myFunct = function($user) {
    return $body;
}; 

echo $myFunct($user);

答案 3 :(得分:2)

这很丑,您实际上不应该这样做,但是您在评论中说,您正在为代码混淆器执行此操作,所以这是我的2美分:

$args = '$user, $number';
$body = 'echo "#$number: Hello $user.\n";';

function _create_function_without_eval($args, $body) {
    $func_name = sprintf('temp_func_%s', md5($body));
    $code = sprintf("<?php if (!function_exists('%s')) {function %s(%s){%s}}", $func_name, $func_name, $args, $body);
    $func_file = tempnam('/tmp', $func_name);
    $handle = fopen($func_file, "w+");
    fwrite($handle, $code);
    fclose($handle);
    include $func_file;
    unlink($func_file);
    return function(...$user_args) use ($func_name) {
      return call_user_func_array($func_name, $user_args); 
    };
}

function _create_function_with_eval($args, $body) {
    $func_name = sprintf('temp_func_%s', md5($body));
    $code = sprintf("if (!function_exists('%s')) {function %s(%s){%s}}", $func_name, $func_name, $args, $body);
    eval($code);
    return function(...$user_args) use ($func_name) {
      return call_user_func_array($func_name, $user_args); 
    };
}

$fn_deprecated = create_function($args, $body);
$fn_with_eval = _create_function_with_eval($args, $body);
$fn_without_eval = _create_function_without_eval($args, $body);

echo $fn_deprecated('Old Bob', '1');
echo $fn_without_eval('Bob without eval', 2);
echo $fn_with_eval('Bob with eval', 3);

在此处实时查看:https://3v4l.org/urQ4k

答案 4 :(得分:0)

注意

eval()语言构造非常危险,因为它允许执行任意PHP代码。因此不鼓励使用它。如果您已经仔细验证了除了使用此构造方法外没有其他选择,请特别注意不要在未经事先正确验证的情况下将任何用户提供的数据传递到其中。

因此Eval是最糟糕的替代品,因为使用eval而弃用了create_function。

为adiinviter pro使用匿名功能。

$b  = function () use ($d,$f1,$c,$ps){
            return gzinflate( base64_decode(str_rot13($ps) ) );
        };

答案 5 :(得分:-2)

PHP开发人员爱你,哈哈哈,看看这里

$user = "John Doe";
$body = 'echo "Hello " . $a;';
$f = create_function('$a', $body);

$f($user);

//out : Hello John Doe

文档PHP官方:create_function(string $args,string $code)