Turtle
Turtle

Reputation: 1656

Parse variables in PHP string

NOTE: Eval is used here in total knowledge, the string parsed is entered by an administrator only, and the purpose is to store instructions in database, without restrictions to the instructions. If you have a good alternative, it is always appreciated, but don't just say "eval is bad".

I have a String in PHP, for example

$myString = "(35*$var1*64)/$var2";

I want to eval() this string, but before, I want to modify all the variables in the string like this:

$var2 -> $_POST['var2']

There may or may not be a blank space after the variable in $myString .

When I eval $myString, PHP throws an error "Undefined variable $var1". PHP read the string and parse the variables, so I guess there should be a way to parse all the variables in the string.

The output should be:

$myStringParsed = "(35*$_POST['var1']*64)/$_POST['var2']";

or an equivalent.

Upvotes: 3

Views: 6067

Answers (3)

Justinas
Justinas

Reputation: 43557

You are using wrong string enclosing quotes. Use '(35*$var1*64)/$var2':

//$var1 = $_POST['var1'];
//$var2 = $_POST['var2'];

$var1 = '10';
$var2 = '20';

$myString = 'return (35 * $var1 * 64) / $var2;';

echo eval($myString);
//1120

Working example of eval


If you want to take any variable from POST, than you can use extract() to get array keys as variables with associated values:

<?php
// Change it to real $_POST
$POST = [
    'var1' => '10',
    'var2' => '20',
];

extract($POST, EXTR_SKIP);

$myString = 'return (35 * $var1 * 64) / $var2;';

echo eval($myString);

Upvotes: 0

Igor R
Igor R

Reputation: 426

Not maybe the best solution, but you can preprocess $_POST variable and generate $variablesString like this:

$variablesString = '';
foreach($_POST as $key => $val) {
    $variablesString .= '$' . $key . ' = ' . $val . ';' . PHP_EOL;
}

eval($variablesString . PHP_EOL . $myString)

For string support you can check if $val is string, and if yes - wrap it with quotes.

Second way

$myString = 'return (35 * $var1 * 64) / $var2;';
$re = "/\\$(\\w*)/im";

preg_match_all($re, $myString, $matches);

foreach($matches[1] as $match) {
    $search = '$' . $match;
    $replace = '$_POST[\'' . $match . '\']';
    $myString = str_replace($search, $replace, $myString);
}
echo eval($myString);

You can check it here

Upvotes: 1

symcbean
symcbean

Reputation: 48387

Assuming you mean....

$myString = '(35*$var1*64)/$var2';

The a more robust solution (consider $myvar10) than that suggested by ASGM is:

$replace=array(
   '/\b\$var1\b/'=>$_POST['var1'], 
   '/\b\$var2\b/'=>$_POST['var2'],
   ...
);
$interpolated=preg_replace(array_keys($replace)
    , $replace, $myString);

Note that I would recommend that you interpolate the string with literals rather than substituting one place holder for another. In addition to eliminating unnecessary processing, it also means you can check the content of the resulting string to ensure it only contains digits and operators (and a restricted number of functions if appropriate).

Upvotes: 0

Related Questions