
本文介绍一种通用、高效的递归 php 函数,用于解析任意深度嵌套的 `and`/`or` 逻辑节点数组,准确计算其布尔结果,适用于 laravel 等 php 应用中的动态规则引擎或条件求值场景。
在构建动态权限控制、业务规则引擎或条件过滤器(如高级搜索、风控策略)时,常需将逻辑结构以 jsON 形式存储并运行时求值。上述数据结构本质上是一棵多叉逻辑表达式树:每个节点含 “nodeType” 字段(”and” 或 “or”),其余键(如 “0”, “1”, “3” 等)为子表达式——这些键名无语义,仅作索引,真正重要的是其值(布尔字面量或子节点对象)。
由于树的深度与分支数完全动态,迭代遍历极易出错且难以维护,递归是自然且最优的选择。核心思路是:
- ✅ 基础情况(Base Case):若当前值为 true 或 false,直接返回;
- ✅ 递归情况(Recursive Case):根据 nodeType 决定短路策略:
- “or” 节点:只要任一子节点返回 true,立即返回 true(OR 短路);
- “and” 节点:只要任一子节点返回 false,立即返回 false(AND 短路);
- ✅ 收尾逻辑:若遍历完所有子节点均未触发短路,则 “or” 返回 false,”and” 返回 true(即默认值取逻辑恒等元)。
以下是经过验证、鲁棒性强的实现:
function evaluateBooleanExpression($expr): bool { // 基础情况:已是布尔值,直接返回 if (is_bool($expr)) { return $expr; } // 非数组或缺少 nodeType,视为无效节点(可按需抛异常) if (!is_array($expr) || !isset($expr['nodeType'])) { throw new InvalidArgumentException('Invalid expression: missing "nodeType" or not an array'); } $isOrNode = $expr['nodeType'] === 'or'; $shortCircuitValue = $isOrNode; // OR 短路于 true;AND 短路于 false // 遍历所有非 "nodeType" 的子项 foreach ($expr as $key => $value) { if ($key === 'nodeType') { continue; } $childResult = evaluateBooleanExpression($value); if ($childResult === $shortCircuitValue) { return $shortCircuitValue; // 触发短路 } } // 未短路:OR 全为 false → 返回 false;AND 全为 true → 返回 true return !$shortCircuitValue; }
使用示例与验证
假设你从数据库或 API 获取如下 json 字符串(注意外层为单元素数组):
$json = '[ { "nodeType": "and", "0": { "nodeType": "and", "0": { "nodeType": "and", "1": true, "2": false }, "3": true }, "2": { "nodeType": "or", "4": false, "5": true } } ]'; $data = json_decode($json, true); $result = evaluateBooleanExpression($data[0]); // 取首个元素 var_dump($result); // 输出: bool(false) ✅ 符合预期(最内层 and(1:true, 2:false) = false,导致顶层 and 整体为 false)
关键注意事项
- ? 键名无关性:函数自动跳过 “nodeType” 键,其余所有键均视为子表达式入口,完全兼容 “0”, “1”, “3”, “4” 等任意数字或字符串键;
- ? 严格类型安全:使用 is_bool() 判定基础值,避免 0/1、”true”/”false” 等松散类型干扰;
- ? 短路优化:无需遍历整棵树,在满足逻辑条件时立即终止,性能随表达式复杂度提升而显著受益;
- ? 错误防护:对缺失 nodeType 或非数组输入主动抛异常,便于调试与集成测试;
- ? laravel 集成建议:可封装为 app/Helpers/LogicEvaluator.php 辅助函数,或定义为 LogicExpression 服务类,配合依赖注入使用。
该方案已通过多层嵌套(含 and→or→and→… 混合)、边界 case(纯叶子节点、空子节点等)充分验证,是生产环境中处理动态布尔逻辑表达式的可靠实践。