PHP Conference Kansai 2025

eval

(PHP 4, PHP 5, PHP 7, PHP 8)

evalОценивает строку как PHP-код

Описание

eval(string $code): mixed

Языковая конструкция интерпретирует строку code как PHP-код.

Выполняемый код наследует область видимости переменных той строки, в которой вызвали языковую конструкцию eval(). Каждая переменная, доступная в строке вызова конструкции, будет доступна для чтения или изменения в выполняемом коде. При этом определяемые в строке кода функции и классы определяются в глобальной области видимости. Компилятор интерпретирует вычисляемый код так, как если бы код подключили отдельным файлом.

Предостережение

Языковая конструкция eval() представляет серьёзную опасность, поскольку разрешает выполнять произвольный PHP-код. Поэтому пользоваться языковой конструкцией не рекомендуют. Пользовательские данные передают в конструкцию только после внимательной предварительной проверки, и только если альтернатив конструкции нет.

Список параметров

code

Корректный PHP-код, который требуется выполнить.

Код нельзя оборачивать открывающим и закрывающим PHP-тегами, поэтому вместо строки '<?php echo "Привет!"; >' в конструкцию передают строку 'echo "Привет!";'. Переключаться между режимом PHP-кода и HTML-разметки помогают открывающие и закрывающие PHP-теги: 'echo "Режим PHP-кода!"; ?>Режим HTML-разметки<?php echo "Снова PHP-код!";'.

Конструкция выполнит только корректный PHP-код, поэтому каждую инструкцию кода потребуется правильно завершить точкой с запятой. Строка 'echo "Привет!"' сгенерирует синтаксическую ошибку, а строка 'echo "Привет!";' сработает.

Инструкция return немедленно завершит выполнение кода.

Код выполнится в области видимости кода, который вызывал конструкцию eval(). Поэтому переменные, которые определили или изменили в вызове eval(), сохранят видимость после завершения вызова конструкции.

Возвращаемые значения

Языковая конструкция eval() возвращает значение null, если только в выполняемом коде не вызывается инструкция return. Начиная с PHP 7 конструкция eval() выбрасывает ошибку ParseError, если в выполняемом коде допустили синтаксическую ошибку. До PHP 7 в таких случаях конструкция eval() возвращала логическое значение false, а следующий код выполнялся в стандартном режиме. Обработчики ошибок, которые регистрируют функцией set_error_handler(), не перехватывают синтаксические ошибки в конструкции eval().

Примеры

Пример #1 Пример выполнения строки PHP-кода языковой конструкцией eval() — простое слияние текста

<?php

$string
= 'чашка';
$name = 'кофе';

$str = 'Это — $string $name.';

echo
$str. "\n";

eval(
"\$str = \"$str\";");

echo
$str. "\n";

?>

Результат выполнения приведённого примера:

Это — $string $name.
Это — чашка кофе.

Примечания

Замечание: Конструкцию нельзя вызывать как функцию переменной или передавать как именованный аргумент, поскольку это языковая конструкция, а не функция.

Подсказка

Как и с остальными функциями или конструкциями языка, которые выводят результат в браузер, для захвата и сохранения вывода конструкции, например, в значении с типом string пользуются функциями управления выводом.

Замечание:

Скрипт завершает работу, если в строке кода возникает фатальная ошибка.

Смотрите также

  • call_user_func() - Вызывает callback-функцию, заданную в первом параметре

Добавить

Примечания пользователей 7 notes

up
474
Anonymous
20 years ago
Kepp the following Quote in mind:

If eval() is the answer, you're almost certainly asking the
wrong question. -- Rasmus Lerdorf, BDFL of PHP
up
43
lord dot dracon at gmail dot com
9 years ago
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!\\\";\');\");');");
?>
up
21
Jeremie LEGRAND
7 years ago
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.
up
27
bohwaz
13 years ago
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.
up
8
catgirl at charuru dot moe
7 years ago
It should be noted that imported namespaces are not available in eval.
up
5
divinity76 at gmail dot com
7 years ago
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
up
6
darkhogg (foo) gmail (bar) com
15 years ago
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 ' );
?>
To Top