如果在PHP中比较字符串,则使用Eval执行

时间:2012-12-20 21:42:05

标签: php string eval

我有一些看起来像这样的代码。

eval('$ruleTrue = '."{$value} {$operator} {$value2};");

我主要从数据库中提取数值并将它们与其他数值进行比较。操作员也来自数据库。可能的运算符是<,>,==。

当比较整数和浮点数时,这非常有效。但是在比较字符串时它会中断。比如..

WORKS: 5> 4 $ ruleTrue = true

不能正常工作: 约翰 - 亚当斯==爱丽丝 $ ruleTrue = true< ---为什么?因为约翰不是==爱丽丝。

由于某些原因,在比较字符串时,我的$ ruleTrue变量返回true。

3 个答案:

答案 0 :(得分:4)

您正在尝试评估此代码:

$ruleTrue = John == Alice;

JohnAlice不是字符串,它们是未定义的常量。你想在它们周围加上引号。但要小心,因为如果您的用户能够编辑数据库中的这些字段,他们可以找到一种方法来取消字符串并执行他们自己的PHP代码,这可能是灾难性的。 Eval非常不安全,你可能不应该使用它。

答案 1 :(得分:1)

确保,如果值是字符串,则它们被“引号”

包围

答案 2 :(得分:1)

表达式John-Adams == Alice有点像(John - Adams) == Alice。左侧试图减去两个字符串(未定义的常量被认为是'裸字',并且等于其名称的字符串化;例如John === 'John'),并且为了理解这种奇怪的操作, PHP将两个字符串都转换为数字。作为整数,两个字符串的值都为0,因此左侧等于0。

一个int。

现在,当PHP想要与==进行比较时,它想要将双方强制转换为相同的类型。在这种情况下,它将转换为int。 Alice 转换为0.双方都为0,他们“明显”相等。

为了防止这种情况发生,您应该在您的值周围加上引号。你也可以考虑使用严格等于运算符(===),除非你真的想要那种类型强制魔法。

或者,如果您有一组已知的运算符,则可以通过创建具有运算符子函数的比较函数来消除eval并使其更安全,更强大。像这样:

function compare($value1, $op, $value2) {
    static $known_ops = array(
        '==' => function($a, $b) { return $a == $b; },
        '!=' => function($a, $b) { return $a != $b; },
        ...

        # you can even make up your own operators.  For example, Perl's 'eq':
        'eq' => function($a, $b) { return "$a" === "$b"; }

        ...
    );
    $func = $known_ops[$op];
    return $func($value1, $value2);
}

...

$ruleTrue = compare($value, $operator, $value2);

现在您不必担心自己的价值观。您必须担心$operator,但如果您让用户输入它而不验证它,那么这只是一个问题。在这种情况下,如果$op不在$known_ops中,您可能想要抛出异常或其他内容,因为如果您离开PHP来处理它,当它尝试使用时,您可能会遇到致命错误致电null