create_function in PHP gets deprecated

<?php

function compute($input){

        $compute = create_function('', 'return '.$input.';');
        return 0 + $compute();
    
}

$test = array(
    '5 + 5',
    '3 +( 2 * 3)',
    '(3 + 2) * 3',
    '3 + 2 * 3',
    '(3-2-1)*3'
    
);

foreach( $test AS $string){
    echo compute( $string);
    echo "<br />";
}

http://sandbox.onlinephpfunctions.com/code/61ee53b5477d7450ff89f4f012915a44e609000b

The code above gets deprecated in PHP 7.2. Most of the other people who had this problem were told to use an anonymous function. But in this case I have no idea how to use it.

Upvotes: 0

Views: 481

Answers (2)

braindigitalis
braindigitalis

Reputation: 558

A simple parser, perhaps recursive descent, or like this one would do the job nicely, if you REALLY wanted to remain using PHP for the entire solution. You can quite easily use such a system to evaluate custom formulas without resorting to eval.

Personally, i wanted something that could evaluate an entire function in php safely (with loops, conditionals etc), so i used a very lightweight javascript interpreter called duktape, which can be compiled into php 7 as a module. You can then call it to evaluate javascript functions, which are simplistic in nature and have no input/output capabilities except for being able to return a value, and take input from the original script.

Here's how i did this:

    /* Execute a javascript function. Requires the duktape extension to be included in PHP.
     * Accepts an array of variables by name to include as parameters to the called code.
     * The code is expected to return a value, which should be scalar (numeric, string or null).
     */
    function jsfunction($inputs, $code)
    {
            $duktape = new Duktape();

            $javascript = "function e() {";
            foreach ($inputs as $name=>$value) {
                    $javascript .= "var " . $name . ' = ' . json_encode((object)$value) . ";\n";
            }
            $javascript .= $code . "}\ne();";

            try {
                    $result = $duktape->eval($javascript);
            }
            catch (Exception $e) {
                    return null;
            }
            return $result;
    }

The parameters must be passed as an array of name/value pairs, e.g. passing ['a'=>42] makes a variable with the name 'a' visible to the javascript, with the value 42. $code contains a javascript function body, without braces around it, which must end with a return statement.

Hope this helps!

Upvotes: 0

symcbean
symcbean

Reputation: 48387

Wow, what a really inefficient way to write your own 'eval()' function. But useful for getting persistence on compromised systems. Perhaps this is the reason for the function being deprecated?

If the problem you are trying to solve is your test case, then either use eval (with validated inputs - /^[^0-9 +-*\/\(\)]$/ ) or use a lib specifically designed for resolving such expressions.

If you are not trying to implement polymorphic code, then anonymous functions are straight forward (which coincidentally implements polymorphic code!):

$compute = function () use ($arg) {
      if (preg_match('/^[^0-9 +-*\/\(\)]$/', $arg)) {
           return eval('return '.$arg . ';');
      }
      return false;
  };

Upvotes: 0

Related Questions