我有一些看起来像这样的代码。
eval('$ruleTrue = '."{$value} {$operator} {$value2};");
我主要从数据库中提取数值并将它们与其他数值进行比较。操作员也来自数据库。可能的运算符是<,>,==。
当比较整数和浮点数时,这非常有效。但是在比较字符串时它会中断。比如..
WORKS: 5> 4 $ ruleTrue = true
不能正常工作: 约翰 - 亚当斯==爱丽丝 $ ruleTrue = true< ---为什么?因为约翰不是==爱丽丝。
由于某些原因,在比较字符串时,我的$ ruleTrue变量返回true。
答案 0 :(得分:4)
您正在尝试评估此代码:
$ruleTrue = John == Alice;
John
和Alice
不是字符串,它们是未定义的常量。你想在它们周围加上引号。但要小心,因为如果您的用户能够编辑数据库中的这些字段,他们可以找到一种方法来取消字符串并执行他们自己的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
。