不知道你有没有这种感觉:一个业务功能看起来很简单,但判断条件却一大堆。
什么用户状态、配置项、商品属性、会员等级……
一大堆 if
/ else
交织在一起,越写越乱,稍微改一个逻辑就要担心影响其他地方。
我之前就遇到这样的情况,一开始还能忍,后来干脆决定:不如自己写一个简单的规则引擎,专门用来处理这些组合判断。
于是就有了这个项目:hejunjie/simple-rule-engine
🚀 这个规则引擎能干嘛?
一句话总结:
这是一个轻量、易用的 PHP 规则引擎,支持多条件组合、动态规则执行,适合业务规则判断、数据校验等场景。
适合用在你项目中的这些地方:
- 复杂业务的多条件判断(比如用户是否满足某个活动要求)
- 数据入库前的规则校验
- 自定义逻辑的配置化、结构化处理
- 写得一手 if 地狱,想抽出来整整齐齐 😅
🌟 为什么要做它?
在实际业务中,很多业务判断逻辑其实都可以归纳为:“一堆字段 + 一些规则 + 多个条件组合”。
原本我们可能是这么写的:
if (
$user['status'] === 'active' &&
$user['age'] >= 18 &&
in_array($user['role'], ['admin', 'editor'])
) {
// ...
}
现在可以这样:
// 定义规则
$rules = [
new Rule('age', '>=', 18, '年龄必须大于等于18岁'),
new Rule('status', '==', 'active', '状态必须为active'),
new Rule('role', 'in', ['admin', 'editor'], '角色需拥有权限'),
];
// 评估结果
$result = Engine::evaluate($rules, $user, 'AND'); // 返回 true 或 false
// 获取详细评估信息(用于获取每条规则的执行情况)
$details = Engine::evaluateWithDetails($rules, $user);
/*
返回示例:
[
['description' => '年龄必须大于等于18岁', 'passed' => true],
['description' => '状态必须为active', 'passed' => true],
['description' => '角色需拥有权限', 'passed' => true]
]
*/
是不是整洁多了?而且如果你把规则放数据库,就能实现“业务判断配置化”了。
🧩 项目特点
- ✅ 轻量易用:无依赖,无框架限制,简单几行就能用
- 🔌 工厂注册机制:你可以自己写新的操作符(Operator)注册进来
- 📦 内置常用操作符:多数常用操作符都支持(可见文章末尾操作符支持列表)
- 🧠 可组合、多条件支持:支持 AND / OR 关系组合,扩展多套规则逻辑很方便
📦 安装方法
composer require hejunjie/simple-rule-engine
🛠️ 示例代码
use Hejunjie\SimpleRuleEngine\Rule;
use Hejunjie\SimpleRuleEngine\Engine;
// 定义规则
$rules = [
new Rule('age', '>=', 18, '年龄必须大于等于18岁'),
new Rule('status', '==', 'active', '状态必须为active'),
new Rule('role', 'in', ['admin', 'editor'], '角色需拥有权限'),
];
$data = ['age' => 20, 'country' => 'China'];
// 简单判断是否通过全部规则
if (Engine::evaluate($rules, $data, 'AND')) {
echo '符合规则';
}
// 获取每一条规则是否通过的详情
foreach (Engine::evaluateWithDetails($rules, $data) as $detail) {
echo $detail['description'] . ':' . ($detail['passed'] ? '✅ 通过' : '❌ 未通过') . PHP_EOL;
}
🔌 自定义操作符
你可以自由的去实现自己的判断逻辑,指定一个操作符,并自由的插入到你的规则中
仅需要实现 OperatorInterface
接口,并通过 OperatorFactory
注册即可:
use Hejunjie\SimpleRuleEngine\Interface\OperatorInterface;
use Hejunjie\SimpleRuleEngine\OperatorFactory;
class CustomizeOperator implements OperatorInterface
{
/**
* 评估方法
*
* @param mixed $fieldValue 用户输入数据
* @param mixed $ruleValue 对比数据
*
* @return bool
*/
public function evaluate(mixed $fieldValue, mixed $ruleValue): bool
{
// TODO: 实现判断逻辑
}
/**
* 操作符名称
*
* @return string
*/
public function name(): string
{
return 'customize';
}
}
// 注册自定义操作符 customize
$factory = OperatorFactory::getInstance();
$factory->register(new CustomizeOperator());
// 可以在定义规则时使用 customize
$rules = [
new Rule('field', 'customize', 'value', '自定义规则描述'),
...
...
];
// Engine::evaluate($rules, $data, 'AND')
// Engine::evaluateWithDetails($rules, $data)
🧩 内置操作符列表
操作符 | 描述 | 额外说明 |
---|---|---|
== | 等于 | 无 |
!= | 不等于 | 无 |
> | 大于 | 无 |
>= | 大于等于 | 无 |
< | 小于 | 无 |
<= | 小于等于 | 无 |
in | 包含于集合中 | 数组:[内容 1,内容 2,…] |
not_in | 不包含于集合中 | 数组:[内容 1,内容 2,…] |
contains | 包含字符串 | 无 |
not_contains | 不包含字符串 | 无 |
start_swith | 以指定字符串开头 | 无 |
end_swith | 以指定字符串结尾 | 无 |
between | 在指定范围内 | 数组:[最大值,最小值] |
not_between | 不在指定范围内 | 数组:[最大值,最小值] |
before_date | 日期早于 | 任意常规日期格式,包括时间戳均可 |
after_date | 日期晚于 | 任意常规日期格式,包括时间戳均可 |
date_equal | 日期相等 | 任意常规日期格式,包括时间戳均可 |
🤔 总结一下
这个规则引擎不是为了解决多么高级的技术难题,它只是一个更优雅的解决方式。
如果你也遇到过类似的 if/else 困扰,希望这个小工具能帮上你一点忙。
欢迎 Star、Issue、PR,一起完善它 🙌
如果你觉得有帮助,点个赞我会更有动力更新下去~