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

Phi*_*l_t 5 php if-statement eval conditional-statements

我正在通过允许dev在条件规则中使用条件语句来创建一个能够处理复杂条件的验证器.

以一组规则为例:

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

然后,PHP将循环执行这些操作requirements并将它们作为代码进行评估,以返回一个布尔值,该布尔值将确定元素是否需要.

使用该eval()功能的问题非常明显.所以我问,鉴于条件陈述是唯一允许的,是否有更安全的方式来做到这一点:

$result = eval(element_name->requirements[0]);
Run Code Online (Sandbox Code Playgroud)

感谢你们.

----更新-----

谢谢麦克和大家的想法,我希望我能标记你所有的答案,因为相当诚实,我结束了使用大家的想法一点点.更多迈克,所以他得到了它.

所以,这可能是将来要考虑的事情,因为它是有条件地验证字段的一种非常有吸引力的方法.我的目标是创造一种直观的方式来实现这一目标.我喜欢简单地在json配置文件中打入条件语句的想法.当然,这将涉及一些严重的安全风险或超级复杂的解析引擎,所以我最终要求开发人员学习我们的条件语言方法,但正如您将看到的,我保持它与原始方法非常相似.我认为拥有简单的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']] 
     }
}
Run Code Online (Sandbox Code Playgroud)

Mik*_*ike 4

为了扩展 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',
                ),
            ),
        ),
    ),
);
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用递归函数循环条件语句,如下所示:

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
Run Code Online (Sandbox Code Playgroud)

当我对其进行 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"
            }]
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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