eval

(PHP 4、PHP 5、PHP 7、PHP 8)

eval将字符串当作 PHP 代码进行求值

说明

eval(string $code): mixed

将给定 code 作为 PHP 来求值。

正在求值的代码继承呼叫 eval() 的行中 变量范围。该行中可用的任何变量都可以在求值代码中读取和修改。但是,定义的所有函数和类都将在全局命名空间中定义。换句话说,编译器将被评估代码视为一个独立 包含 的文件。

小心

eval() 函数结构非常危险,因为它允许执行任意 PHP 代码。因此,不鼓励使用。如果您已仔细验证没有其他选择来使用此结构,请特别注意不要向其中传递任何由用户提供的数据,而不要事先对其进行验证。

参数

code

要评估有效的 PHP 代码。

该代码不能包裹在 PHP 标记的开始和结束位置,即必须传递 'echo "Hi!";' 而不是 '<?php echo "Hi!"; ?>'。通过使用适当的 PHP 标记仍然可以离开和重新进入 PHP 模式,例如:'echo "In PHP mode!"; ?>In HTML mode!<?php echo "Back in PHP mode!";'

除此之外,传递的代码必须是有效的 PHP 代码。其中包括必须使用分号正确终止所有语句。例如,'echo "Hi!"' 将导致解析错误,而 'echo "Hi!";' 将起作用。

return 语句将立即终止代码的求值。

代码将在调用 eval() 的代码范围内执行。因此,在 eval() 调用中定义或更改的任何变量在终止后仍将可见。

返回值

eval() 返回 null,除非评估代码中的 return 被调用,在这种情况下,传递给 return 的值将被返回。从 PHP 7 开始,如果评估代码中存在语法错误,eval() 将引发 ParseError 异常。在 PHP 7 之前,这种情况下 eval() 返回 false,并且继续正常执行后续代码。无法使用 set_error_handler() 捕捉 eval() 中的语法错误。

示例

示例 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";
?>

上面示例将输出

This is a $string with my $name in it.
This is a cup with my coffee in it.

注释

注释: 因为这是语言构造而不是函数,所以它不能使用 变量函数命名参数 来调用。

提示

与任何直接向浏览器输出其结果的内容一样,输出控制函数 可用于捕获此函数的输出,并将其保存在 字符串 中(例如)。

注释:

如果评估代码出现致命错误,则整个脚本将退出。

另请参阅

添加注释

用户提交的注释 8 条注释

up
471
佚名
20 年前
谨记以下引言

如果 eval() 是答案,那么你几乎肯定会问
错误的问题。——PHP BDFL Rasmus Lerdorf
up
42
lord dot dracon at gmail dot com
9 年前
eval() 中的盗梦空间

<pre>
盗梦空间开始
<?php
eval("echo '盗梦空间 1 级...\n'; eval('echo \"盗梦空间 2 级...\n\"; eval(\"echo \'盗梦空间 3 级...\n\'; eval(\'echo \\\"边缘!\\\";\');\");');");
?>
up
21
Jeremie LEGRAND
7 年前
至少在 PHP 7.1+ 中,如果被评估的代码产生致命错误,eval() 会终止脚本。例如
<?php
@eval('$content = (100 - );');
?>

(即使它在手册中,我不确定它在 5.6 中是否这样,但无论如何)
要捕获它,我必须执行以下操作
<?php
try {
eval(
'$content = (100 - );');
} catch (
Throwable $t) {
$content = null;
}
?>

这是我发现捕获错误并隐藏错误事实的唯一方法。
up
25
bohwaz
12 年前
如果你想要允许数学输入,并确保输入是正确的数学而不是某些黑客代码,你可以尝试以下操作

<?php

$test
= '2+3*pi';

// 去除空白符号
$test = preg_replace('/\s+/', '', $test);

$number = '(?:\d+(?:[,.]\d+)?|pi|π)'; // 数字格式
$functions = '(?:sinh?|cosh?|tanh?|abs|acosh?|asinh?|atanh?|exp|log10|deg2rad|rad2deg|sqrt|ceil|floor|round)'; // 允许的 PHP 函数
$operators = '[+\/*\^%-]'; // 允许的数学运算符
$regexp = '/^(('.$number.'|'.$functions.'\s*\((?1)+\)|\((?1)+\))(?:'.$operators.'(?2))?)+$/'; // 最终 regexp,主要用于递归模式

if (preg_match($regexp, $q))
{
$test = preg_replace('!pi|π!', 'pi()', $test); // 将 pi 替换为 pi 函数
eval('$result = '.$test.';');
}
else
{
$result = false;
}

?>

我不能完全保证能够阻挡所有恶意代码,也不能阻挡畸形代码,但比下面允许畸形代码如 '2+2+' 导致报错的 matheval 函数要好。
up
7
charuru dot moe 上的 catgirl
6 年前
值得注意的是,导入的命名空间在 eval 中不可用。
up
4
gmail dot com 上的 divinity76
7 年前
依我之见,这是更好的 eval 替代品

<?php
函数 betterEval($code) {
$tmp = tmpfile ();
$tmpf = stream_get_meta_data ( $tmp );
$tmpf = $tmpf ['uri'];
fwrite ( $tmp, $code );
$ret = include ($tmpf);
fclose ( $tmp );
return
$ret;
}
?>

- 为什么?betterEval 遵循正常的 php 开头和结尾标签约定,不必从源代码中剥离 `<?php?>`。如果存在解析错误,它总是抛出 ParseError,而不是返回 false(注意:此问题已在 php 7.0 中针对正常的 eval() 修复)。- 还有一些关于异常回溯的内容
up
6
darkhogg (foo) gmail (bar) com
14 年前
以下代码

<?php
eval( '?> foo <?php' );
?>

不抛出任何错误,但打印开头标签。
在开头标签后面添加空格可以修复此问题

<?php
eval( '?> foo <?php ' );
?>
up
0
remindfwd at gmail dot com
4 天前
请注意

<?php

echo eval( '$var = (20 - 5);' ); // 没有任何显示

echo ' someString ' . eval( 'echo $var = 15;' );
// 输出:15 someString

// 或
echo ' someString ' . eval( 'echo $var = 15;' ) . ' otherString ';
// 输出:15 someString otherString

// 或
echo ' someString ' . eval( 'echo $var = 15;' ) . ' otherString ' . '...' .eval( 'echo " __ " . $var = 10;' );
// 输出:15 __ 10 someString otherString ...

?>
To Top