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

PHP 7.2 - How to create anonymous function dynamically when having function body in a string

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

例如

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

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

$myFunct($user);

如有任何帮助,我们将不胜感激。

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

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

快速解决方案是使用 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 的工作方式.

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

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

它可以接受带有任何 arg 参数的匿名函数:

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

你可以试试这个:

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

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

echo $myFunct($user);

嗯,这很丑陋,你真的不应该这样做,但你在评论中说你这样做是为了代码混淆器,所以这是我的 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

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)

注意

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

所以 Eval 是最差的替代品,create_function 因为使用 eval 而被弃用。

为 adiinviter pro 使用匿名函数。

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