【问题标题】:Using Eval to perform if comparison of strings in PHP使用 Eval 执行 PHP 中的字符串比较
【发布时间】:2012-12-20 21:42:05
【问题描述】:

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

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

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

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

作品: 5 > 4 $ruleTrue = true

不能正常工作: 约翰-亚当斯 == 爱丽丝 $ruleTrue = true

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

【问题讨论】:

    标签: php string eval


    【解决方案1】:

    您正在尝试评估此代码:

    $ruleTrue = John == Alice;
    

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

    【讨论】:

    • 未定义的常量评估为包含其名称的字符串,这显然不相等。至少按字符串...
    • 相信我,我已经提出反对这种使用 eval 的论点,但我没有获胜。所以我一直在适应。
    • 我想我知道为什么我是真实的......我的字符串有一个破折号。例如,假设字符串 1 是 John-Adams,字符串 2 是“Alice”。 John-Adams == Alice 返回 true。
    • 啊,是的,减号使它将字符串解释为 0,然后 Alice 也被解释为 0。 0 - 0 == 0
    • @allencoded:查看我的更新答案,以获得更安全、更强大的替代 eval
    【解决方案2】:

    表达式John-Adams == Alice 的解析有点像(John - Adams) == Alice。左侧试图减去两个字符串(未定义的常量被认为是“裸词”,并且等于它们的名称的字符串化;例如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 时,您可能会遇到致命错误.

    【讨论】:

      【解决方案3】:

      确保,如果值是字符串,它们用“引号”括起来

      【讨论】:

        猜你喜欢
        • 2020-09-21
        • 1970-01-01
        • 1970-01-01
        • 2013-12-21
        • 1970-01-01
        • 2013-08-12
        • 2011-10-03
        • 1970-01-01
        • 2012-10-05
        相关资源
        最近更新 更多