13

How do I create an anonymous function dynamically when I have function body in a string.

For e.g.

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

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

$myFunct($user);

Any help would be much appreciated.

P.S. I'm looking for a replacement for create_function() functionality which was there in prior versions of PHP. Just like in create_function() where we could pass the function body as a string, I would like to define anonymous function's body off the string variable.

7
  • 9
    with evil eval. BUT if you think you need to do this, there's something wrong. Commented Sep 30, 2018 at 15:04
  • I'm writing a custom code obfuscator for which this is needed. In prior versions of PHP, this was pretty straight forward with create_function(). I'm looking for a replacement in PHP 7.2 for create_function() functionality where we used to pass function body as a string. Commented Sep 30, 2018 at 15:05
  • 2
    stackoverflow.com/a/951868/4830296 Commented Sep 30, 2018 at 15:07
  • stackoverflow.com/a/43694834/2469308 Commented Sep 30, 2018 at 15:10
  • 1
    It is unsafe for this and it has been removed. Read, please stackoverflow.com/a/642331/8352809 Commented Oct 7, 2018 at 12:20

6 Answers 6

20
+50

If you have explored all other options and are absolutely sure the only way to accomplish your goals is to define custom functions at runtime using code that's in a string, you have two alternatives to using create_function.

The quick solution is to just use 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

However, eval() can be disabled. If you need this sort of functionality even on servers where eval is not available, you can use the poor man's eval: write the function to a temporary file and then include it:

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

In all honesty though, I strongly recommend against these approaches and suggest you find some other way to accomplish your goal. If you're building a custom code obfuscator, you're probably better off creating a php extension where the code is de-obfuscated prior to execution, similar to how ionCube Loader and Zend Guard Loader work.

Sign up to request clarification or add additional context in comments.

2 Comments

"code is de-obfuscated prior to execution, similar to how ionCube Loader and Zend Guard Loader work" - this is not even close to how those extensions work :) ionCube and Zend protection works by compiling PHP to bytecode, protecting the bytecode, and executing the compiled code with an engine in the respective Loaders. For ionCube, code can also be encrypted with keys that are never stored, requiring the protected PHP application itself to produce decryption keys on demand in order to be able to decrypt and run further layers of the application. There's no PHP source in the encoded files :)
@Nick Wow, thanks for commenting! Your post from a few years ago is an interesting look into ionCube. I stand corrected :)
2

You can use the callable type hint. Here is an example

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

It can take an anonymous function with any arg params:

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

Comments

2

You can try this:

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

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

echo $myFunct($user);

Comments

2

Well this is ugly and you shouldn't really do this, but you said in a comment that you're doing this for a code obfuscator so here are my 2 cents:

$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);

See it live here: https://3v4l.org/urQ4k

Comments

2

Caution

The eval() language construct is very dangerous because it allows execution of arbitrary PHP code. Its use thus is discouraged. If you have carefully verified that there is no other option than to use this construct, pay special attention not to pass any user provided data into it without properly validating it beforehand.

so Eval is the worst replacement, create_function is depreicated because of using eval.

use anonymous functions for adiinviter pro.

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

Comments

-3

PHP developers love you hahaha look here

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

$f($user);

//out : Hello John Doe

Documentation PHP official : create_function(string $args,string $code)

1 Comment

Because the question is about not using create_function with PHP 7.2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.