php - 尝试不在 php 中使用 eval() 来评估带有条件语句的字符串

标签 php if-statement eval conditional-statements

我正在创建一个验证器,它可以通过允许开发人员在条件规则中使用条件语句来处理复杂的条件。

以一组规则为例:

...
"element_name":{
     "required": "conditional",
     "conditions" : {
         "requirements" : "(4 < 5)",
         "requirements" : "('something' == 'something_else')" 
     }
}
...

然后 PHP 将做的是遍历那些 requirements 并将它们评估为代码以返回一个 bool 值,该 bool 值将确定该元素是否是必需的。

使用eval() 函数的问题非常明显。所以我问,考虑到条件语句是唯一允许的,有没有比以下更安全的方法:

$result = eval(element_name->requirements[0]);

谢谢你们。

----更新-----

谢谢 Mike 和大家的想法,我希望我能把你们都标记为答案,因为老实说,我最终使用了每个人的一点点想法。更多迈克的,所以他明白了。

所以,这可能是将来要研究的东西,因为它是一种非常有吸引力的有条件地验证字段的方法。我的目标是创建一种直观的方式来解决这个问题。我喜欢在 json 配置文件中简单地加入条件语句的想法。当然,这会涉及一些严重的安全风险或 super 复杂的解析引擎,所以我不再要求开发人员学习我们的条件语言方法,但正如您将看到的,我保持它与原始方法非常相似。我认为拥有简单的 API 很重要,否则您将阻碍在您的平台上进行开发。检查一下:

"element_name":{
     "required": "conditional",
     "conditions" : {
         "<" : ['4', '5'],
         "==" : [':element_id', ':other_element'], // will grab the values of those elements and compare
         "exp" : [['something', '==', 'something_else'], 'OR', [':other_element', '!=', '0']] 
     }
}

最佳答案

为了扩展 dethtron5000 的答案,我想到的一种方法是让开发人员将他的条件分解成更多的多维条件事物,并使用递归函数对其进行循环。在每个级别,您都会有一个“运算符”,它可以是“AND”或“OR”(至少我希望这被称为“运算符”,如果不能随意更改的话)。

在您的示例中,您有:(32 < 40 AND 10 > 5 OR 20 == 10)

(看起来你正在对条件进行 json_encoding,所以我从以下 PHP 数组开始,然后从那里向后工作。我假设你可以 json_decode 你的开发人员提供给你的东西来获得有效的 PHP 数组) .上面的示例将表示为以下 PHP 数组:

$arr = array(
    'required' => 'conditional',
    'conditions' => array(
        'requirements' => array(
            'operator' => 'OR', // this makes it so that if any conditions at this level are true, it returns true
            0 => array(
                'operator' => 'AND', // this makes it so that all the conditions at this sub-level need to be satisfied to return true
                array(
                    'conditional1' => 32,
                    'conditional2' => 40,
                    'operation' => 'lessthan',
                ),
                array(
                    'conditional1' => 10,
                    'conditional2' => 5,
                    'operation' => 'greaterthan',
                ),
            ),
            1 => array(
                // Since there is only one condition here, it is not necessary to specify "AND" or "OR"
                array(
                    'conditional1' => 20,
                    'conditional2' => 10,
                    'operation' => 'equals',
                ),
            ),
        ),
    ),
);

然后您可以使用这样的递归函数遍历条件:

function check_req(Array $reqs) {
    $operator = (isset($reqs['operator'])) ? $reqs['operator'] : 'AND';
    unset($reqs['operator']);
    foreach ($reqs as $req) {
        if (isset($req['operation'])) {
            switch ($req['operation']) {
                case 'lessthan':
                    $valids[] = $req['conditional1'] < $req['conditional2'];
                    break;
                case 'greaterthan':
                    $valids[] = $req['conditional1'] > $req['conditional2'];
                    break;
                case 'equals':
                    $valids[] = $req['conditional1'] == $req['conditional2'];
                    break;
            }
        }
        else {
            $valids[] = check_req($req);
        }
    }
    if ($operator == 'OR') {
        foreach ($valids as $valid) {
            if ($valid == true) {
                return true;
            }
        }
        return false;
    }
    else {
        foreach ($valids as $valid) {
            if ($valid == false) {
                return false;
            }
        }
        return true;
    }
}

var_dump(check_req($arr['conditions']['requirements'])); // true in this case

当我对其进行 json_encode 时,我得到:

{
    "required":"conditional",
    "conditions":{
        "requirements":{
            "operator":"OR",
            "0":{
                "operator":"AND",
                "0":{
                    "conditional1":32,
                    "conditional2":40,
                    "operation":"lessthan"
                },
                "1":{
                    "conditional1":10,
                    "conditional2":5,
                    "operation":"greaterthan"
                }
            },
            "1":[{
                "conditional1":20,
                "conditional2":10,
                "operation":"equals"
            }]
        }
    }
}

我假设这是开发人员必须为您提供的。

关于php - 尝试不在 php 中使用 eval() 来评估带有条件语句的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17871112/

相关文章:

php - 无法在 Twitter API 搜索中获得去年的结果

php - 数据模式对话框不显示

php - 同一页面上的多个表单 - 如果为空

ruby - 如何从 Ruby 中的 CSV 标题行创建变量

php - SQL 上的组项目

mysql - 检查存储过程中的 var 是否为 NULL

python - 如何决定在不使用 'if' 语句的情况下创建子类

java - 如何将 for 循环与 if-else 语句结合使用

asp.net - 如何在三元运算符中使用 ASP.NET Eval() 函数?

perl - eval 内出现词法变量为 "not available"的警告的原因是什么