使用PHP eval()捕获某些错误

时间:2011-04-01 22:21:41

标签: php eval

UPDATE:我意识到eval()存在缺陷,但我“应该”将它用于此特定问题。因此,任何解决问题的方法都需要牢记这一点。

我刚开始使用PHP,我正在使用正则表达式(使用preg_match(),具体而言)和eval()实现一个非常有限的计算器。计算器的一个特性是,当它被赋予任何形式的错误输入时,会显示由我编写的简单错误消息,而不是默认的PHP错误。这适用于大多数不良输入(带字母的字符串,连续多个运算符等),但我无法捕捉到其他类型的错误。特别是输入:

0/0

等等

2--1

后一个表达式在技术上很好,但我不需要处理它(大概是为了保持我们的代码更简单,因为这是一个简单的项目让我们熟悉PHP)并且可以输出我的简单错误消息作为响应。计算器不支持括号,因此表达式如

2-(-1)

无效。麻烦的是,我似乎无法弄清楚当遇到这样的事情时eval()会返回什么,如果它甚至根本没有返回。

eval()总是会返回吗?我已经阅读了几次eval()文档,但似乎无法弄清楚我应该检查哪种类型的东西。我宁愿解释一下要检查什么以及为什么而不是简单地盲目地检查返回值及其补充,直到我弄明白为止。下面是上面描述的两个错误的屏幕截图(我没有足够的声誉将它们嵌入到这里)。任何帮助将不胜感激!

Division by zero error

Multiple operator error

1 个答案:

答案 0 :(得分:2)

这可能看起来很苛刻,但不要这样做!不要那样使用eval(),这很危险。除了它是一种更多更安全的做事方式之外,您还可以通过编写一个简单的tokeniser来打破计算器的输入,然后使用Dijkstra的Shunting Yard algorithm来( a)将其转换为可由堆栈计算机评估的内容,并(b)识别令牌流中的意外令牌(例如您期望数字的运算符)。

eval()无法保证运行,因为您不只是评估简单表达式,而是评估任意代码。

如果您必须使用eval(),请使用set_error_handler()@错误抑制运算符来拦截错误,然后再向用户吐出错误。您可以使用error_reporting()函数来判断捕获的错误是否已使用@抑制。