Kepp the following Quote in mind:
If eval() is the answer, you're almost certainly asking the
wrong question. -- Rasmus Lerdorf, BDFL of PHPeval
Почист и полокален преглед на PHP референцата, со задржана структура од PHP.net и подобра читливост за примери, секции и белешки.
eval
Референца за `function.eval.php` со подобрена типографија и навигација.
eval
(PHP 4, PHP 5, PHP 7, PHP 8)
eval — Оцени стринг како PHP код
= NULL
Ја проценува дадената code како PHP.
Кодот што се проценува го наследува опсег на променливи од линијата на која се случува eval() повикот. Сите променливи достапни на таа линија ќе бидат достапни за читање и модификација во проценетиот код. Сепак, сите дефинирани функции и класи ќе бидат дефинирани во глобалниот именски простор. Со други зборови, компајлерот го смета проценетиот код како да е посебен included file.
На eval() јазична конструкција е многу опасно бидејќи дозволува извршување на произволен PHP код. Неговата употреба оттука е обесхрабрена. Ако внимателно сте провериле дека нема друга опција освен да ја користите оваа конструкција, обрнете посебно внимание да не поминувате никакви податоци обезбедени од корисникот во него без соодветно да ги валидирате претходно.
Параметри
code-
Валиден PHP код за проценување.
Кодот не смее да биде завиткан во отворање и затворање PHP тагови, т.е.
'echo "Hi!";'мора да се помине наместо'<?php echo "Hi!"; ?>'. It is still possible to leave and re-enter PHP mode though using the appropriate PHP tags, e.g.'echo "In PHP mode!"; ?>In HTML mode!<?php echo "Back in PHP mode!";'.Освен тоа, поминатиот код мора да биде валиден PHP. Ова вклучува дека сите изрази мора правилно да бидат завршени со точка и запирка.
'echo "Hi!"'на пример ќе предизвика грешка при парсирање, додека'echo "Hi!";'ќе работи.А
returnизјавата веднаш ќе го прекине оценувањето на кодот.Кодот ќе се изврши во опсегот на кодот што го повикува eval(). Така, сите променливи дефинирани или променети во eval() повикот ќе останат видливи откако ќе заврши.
Вратени вредности
eval() returns null unless
return се повикува во оценетиот код, во кој случај вредноста предадена на return се враќа. Од PHP 7, ако има грешка при парсирање во оценетиот код, eval() фрла ParseError исклучок. Пред PHP 7, во овој случај eval() returned
false и извршувањето на следниот код продолжи нормално. Не е можно да се фати грешка при парсирање во eval()
using set_error_handler().
Примери
Пример #1 eval() пример - едноставно спојување текст
<?php
$string = 'cup';
$name = 'coffee';
$str = 'This is a $string with my $name in it.';
echo $str. "\n";
eval("\$str = \"$str\";");
echo $str. "\n";
?>Пример #1 Пример што покажува затворачка ознака што го опфаќа последниот нов ред
This is a $string with my $name in it. This is a cup with my coffee in it.
Белешки
Забелешка: За автоматско вклучување на датотеки во скрипти, видете исто така Бидејќи ова е конструкција на јазикот, а не функција, не може да се повика користејќи, или именувани аргументи.
Како и со се што го прикажува својот резултат директно на прелистувачот, функциите за контрола на излезот може да се користат за да се фати излезот на оваа функција и да се зачува во string (на пример).
Забелешка:
Во случај на фатална грешка во оценетиот код, целото скрипт излегува.
Белешки од корисници Управување со PDO конекции
Inception with eval()
<pre>
Inception Start:
<?php
eval("echo 'Inception lvl 1...\n'; eval('echo \"Inception lvl 2...\n\"; eval(\"echo \'Inception lvl 3...\n\'; eval(\'echo \\\"Limbo!\\\";\');\");');");
?>At least in PHP 7.1+, eval() terminates the script if the evaluated code generate a fatal error. For example:
<?php
@eval('$content = (100 - );');
?>
(Even if it is in the man, I'm note sure it acted like this in 5.6, but whatever)
To catch it, I had to do:
<?php
try {
eval('$content = (100 - );');
} catch (Throwable $t) {
$content = null;
}
?>
This is the only way I found to catch the error and hide the fact there was one.If you want to allow math input and make sure that the input is proper mathematics and not some hacking code, you can try this:
<?php
$test = '2+3*pi';
// Remove whitespaces
$test = preg_replace('/\s+/', '', $test);
$number = '(?:\d+(?:[,.]\d+)?|pi|π)'; // What is a number
$functions = '(?:sinh?|cosh?|tanh?|abs|acosh?|asinh?|atanh?|exp|log10|deg2rad|rad2deg|sqrt|ceil|floor|round)'; // Allowed PHP functions
$operators = '[+\/*\^%-]'; // Allowed math operators
$regexp = '/^(('.$number.'|'.$functions.'\s*\((?1)+\)|\((?1)+\))(?:'.$operators.'(?2))?)+$/'; // Final regexp, heavily using recursive patterns
if (preg_match($regexp, $q))
{
$test = preg_replace('!pi|π!', 'pi()', $test); // Replace pi with pi function
eval('$result = '.$test.';');
}
else
{
$result = false;
}
?>
I can't guarantee you absolutely that this will block every possible malicious code nor that it will block malformed code, but that's better than the matheval function below which will allow malformed code like '2+2+' which will throw an error.The following code
<?php
eval( '?> foo <?php' );
?>
does not throw any error, but prints the opening tag.
Adding a space after the open tag fixes it:
<?php
eval( '?> foo <?php ' );
?>imo, this is a better eval replacement:
<?php
function betterEval($code) {
$tmp = tmpfile ();
$tmpf = stream_get_meta_data ( $tmp );
$tmpf = $tmpf ['uri'];
fwrite ( $tmp, $code );
$ret = include ($tmpf);
fclose ( $tmp );
return $ret;
}
?>
- why? betterEval follows normal php opening and closing tag conventions, there's no need to strip `<?php?>` from the source. and it always throws a ParseError if there was a parse error, instead of returning false (note: this was fixed for normal eval() in php 7.0). - and there's also something about exception backtraces