1

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

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

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

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

作品:5 > 4 $ruleTrue = true

不能正常工作:John-Adams == Alice $ruleTrue = true <--- 为什么?因为约翰不是爱丽丝的==。

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

4

3 回答 3

4

您正在尝试评估此代码:

$ruleTrue = John == Alice;

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

于 2012-12-20T21:46:41.793 回答
2

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

一个整数。

现在,当 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

于 2012-12-20T21:57:45.053 回答
1

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

于 2012-12-20T21:45:42.033 回答