执行php表达式字符串,相比于eval,create_function也许是个更好的选择……

时间:2021-05-06 19:15:47

学过js的人都知道,js里有个eval函数,eval() 函数可计算某个字符串,并执行其中的 JavaScript 代码。

<script type="text/javascript">

eval("x=10;y=20;document.write(x*y)")

document.write(eval("2+2"))

var x=10
document.write(eval(x+17))

</script>

200
4
27


而在PHP里也有执行php表达式的字符串的eval,但是要注意的是它不是一个函数了。官方原文:eval() is a language construct and not a function.

我们可以自己验证下:

var_dump(function_exists('eval'));一运行,打出值boolean false,由此可证eval真不是一个函数,只是语言结构体。eval是zend的,因此不是PHP_FUNCTION 函数。

$x = 3;
$y = 2;
echo eval('return ($x + $y)*2;');

结果输出10;

eval() 函数把字符串按照 PHP 代码来计算,该字符串必须是合法的 PHP 代码,且必须以分号结尾。如果没有在代码字符串中调用 return 语句,则返回 NULL。如果代码中存在解析错误,则 eval() 函数返回 false。注意:如果使用双引号,则需要对变量符号$进行转义,即在$前面加反斜杠\;该函数对于在数据库文本字段*日后计算而进行的代码存储很有用。

官方还有写着这样一段话:

The eval() language construct isvery dangerous because it allows execution of arbitrary PHP code.Its use thus is discouraged. If you have carefully verified that there is no other option than to use this construct, pay special attentionnot to pass any user provided data into it without properly validating it beforehand.  

主要大意:eval()的语言结构非常危险,因为它允许任意代码执行。因此,它的用途是令人泄气的。如果您仔细验证了没有其他选项比使用此结构,特别注意不要将任何用户提供的数据传递给它,没有事先正确地验证它。

官方告诉我们这家伙不是很靠谱,来者不拒,不管传给它什么,它全盘照收,这是非常危险的。既然这么危险,我们一般还是少用它,其实我们可以禁用它,至于怎么禁用,我们这里就不叙述了,大家可自行百度。

其实,对于执行php表达式字符串,php还是有提供了其他的解决办法的,不然怎么叫世界上最好的编程语言呢………O(∩_∩)O哈哈~

我们要说的是,可以用匿名函数的思想来解决这问题,用php函数create_function(),官方原文:Create an anonymous (lambda-style) function,就是创建一个匿名函数的啦。

那么对于上面的问题,我们可以这样来做:

$create_function = create_function('$x,$y','return ($x + $y)*2;');
echo $create_function(2,3);

输出10.

但是也说了一句话:

This function internally performs an eval() and as such has the same security issues aseval(). Additionally it has bad performance and memory usage characteristics.If you are using PHP 5.3.0 or newer a nativeanonymous function should be used instead.  

就是说,性能和内存上有时不够友好哦。但至少比eval会好点儿哦。官方说了,如果用5.3.0及以上新版本,可以用匿名函数来替代。

大概如下所示:

	$a = 5;
	$b = 6;
	$aa = function($a,$b){
		return ($a + $b)*2;
	};//注意,这里需要加分号,否则会报错,这不同于if……else……;for(){}里面的{}
        var_dump($aa($a,$b));

输出:int 22。

闭包函数也可以作为变量的值来使用。PHP 会自动把此种表达式转换成内置类 Closure 的对象实例。把一个 closure 对象赋值给一个变量的方式与普通变量赋值的语法是一样的,最后也要加上分号:

需要注意的是,如下的调用会报错:

echo $aa;//Catchable fatal error: Object of class Closure could not be converted to string

而这样调用var_dump($aa);//object(Closure)[1]。