数据库存储的字符串逻辑规则作为条件判断始终返回TRUE的技术问询
解决数据库存储的字符串逻辑表达式无法正确判断的问题
这问题我之前也踩过坑!核心原因很简单:你把字符串类型的逻辑表达式直接丢进if判断里了——在PHP中,只要是非空字符串,都会被当作true处理,不管字符串内容本身的逻辑是对是错。就像你例子里的"(20 > 3) and (20 < 5)",哪怕这个表达式的实际逻辑是false,但它作为非空字符串,if($www)永远会返回true,自然会执行commission granted的日志。
下面给你两种可行的解决方案,按需选择:
方案1:使用eval()执行表达式(简单但需注意安全)
eval()可以把字符串当作PHP代码执行,刚好能帮你把字符串表达式转换成实际的布尔判断。但一定要记住:eval()是高危函数,如果你的规则来自用户输入,必须做严格的安全校验!
示例代码:
$www = $rule->logic; // 比如值为 "(20 > 3) and (20 < 5)" // 第一步:安全校验,只允许合法的逻辑表达式字符 // 这里的正则只允许数字、空格、括号、比较运算符、逻辑运算符 if (preg_match('/^[\d\s()><=!&|]+$/', $www)) { // 用eval执行表达式并返回结果 $isValid = eval("return $www;"); if ($isValid) { $this->logger->debug('commission granted'); } else { $this->logger->debug('commission noooo'); } } else { // 非法表达式,记录错误日志并处理 $this->logger->error('Invalid logic rule detected'); }
⚠️ 重要提醒:
- 一定要通过正则或白名单过滤掉所有非法字符,比如
;、$、function这些可能用来执行恶意代码的元素。 - 如果你的规则是系统内部生成、不会被外部篡改的,那
eval()是最快捷的方案;但如果规则可能来自用户输入,千万不要直接用eval()!
方案2:自定义表达式解析器(安全但稍复杂)
如果担心eval()的安全问题,你可以自己写一个简单的解析器,手动解析字符串里的逻辑表达式。这种方式虽然麻烦,但完全避免了代码注入的风险。
假设你的规则格式比较固定(比如都是(数字 运算符 数字) and/or (数字 运算符 数字)的结构),可以用下面的示例代码:
$ruleStr = $rule->logic; // 拆分逻辑表达式的各个部分 // 先去掉括号,按and/or拆分条件 $conditions = preg_split('/\s+(and|or)\s+/', str_replace(['(', ')'], '', $ruleStr)); // 提取逻辑运算符(and/or) preg_match_all('/\s+(and|or)\s+/', $ruleStr, $operatorMatches); $operators = $operatorMatches[1]; $finalResult = true; foreach ($conditions as $index => $condition) { // 拆分单个条件里的左值、运算符、右值 preg_match('/(\d+)\s*(>|>=|<|<=|==|!=)\s*(\d+)/', $condition, $matches); $left = (int)$matches[1]; $op = $matches[2]; $right = (int)$matches[3]; // 判断当前条件是否成立 $currentResult = match($op) { '>' => $left > $right, '>=' => $left >= $right, '<' => $left < $right, '<=' => $left <= $right, '==' => $left == $right, '!=' => $left != $right, default => false }; // 结合逻辑运算符计算最终结果 if ($index === 0) { $finalResult = $currentResult; } else { $operator = $operators[$index - 1]; $finalResult = $operator === 'and' ? ($finalResult && $currentResult) : ($finalResult || $currentResult); } } // 根据最终结果执行日志 if ($finalResult) { $this->logger->debug('commission granted'); } else { $this->logger->debug('commission noooo'); }
这种方案的优势是完全可控,你可以根据自己的规则格式扩展解析逻辑,比如支持更多运算符、浮点数等,而且绝对安全,不会执行任何未知代码。
总结
- 你当前的问题本质是字符串与布尔值的类型混淆,PHP会把非空字符串直接判定为
true,所以需要把字符串转换成实际的逻辑判断。 - 如果规则是内部可控的,用
eval()加安全校验是最快的解决方式; - 如果规则可能来自外部输入,或者你追求更高的安全性,自定义解析器是更稳妥的选择。
内容的提问来源于stack exchange,提问作者Shiromi
相关产品推荐
相关产品推荐

