mpoiriert / business-rule-engine
可重用库
Requires
- mpoiriert/invoker: *
- psr/log: *
- symfony/yaml: *
Requires (Dev)
- phpunit/phpunit: 3.7.*
This package is auto-updated.
Last update: 2024-09-09 13:16:49 UTC
README
实现规范模式的引擎
要使用业务引擎,您需要实例化一个IBusinessRuleEngine类并将其分配给一个IRuleProvider。IRuleProvider负责根据名称提供规则。规则只是一个附加名称的可调用对象。
$businessRuleEngine = new \Nucleus\BusinessRuleEngine\BusinessRuleEngine(); $ruleProvider = new \Nucleus\BusinessRuleEngine\InMemoryRuleProvider(); $businessRuleEngine->setRuleProvider($ruleProvider); $ruleProvider->setRule('ruleTrue',function(){ return true; }); $ruleProvider->setRule('ruleFalse',function(){ return false; });
将规则实现为一个只关注此的类的一个简单方法就是使用__invoke魔术方法。
从那里,您可以使用规则规范调用业务规则引擎的方法
$businessRuleEngine->check("ruleTrue");//true $businessRuleEngine->check("ruleFalse");//false $result = $businessRuleEngine->getFirstMatch( array( "check1" => "ruleFalse", "check2" => "ruleTrue", ) ); echo $result;//check2 $result = $businessRuleEngine->getFirstMatch( array( "check1" => "ruleFalse", "check2" => "ruleTrue", "check3" => "ruleTrue", ) ); var_export($result);// array('check2','check3')
规则规范
规则规范是规则名称和Yaml中默认参数的字符串连接。如果您想调用规则toto,默认参数param1 = 1,param2 = array(1,2),它将看起来像这样
"toto{param1:1,param2[1,2]}"
如果您想在规则前添加一个!,使其变为false,那么您不需要向规则传递参数来表示不匹配
"!toto{param1:1,param2[1,2]}"
如果您想检查2个或更多规则必须验证,您可以传递一个规则数组
array("toto{param1:1,param2[1,2]}","!toto{param1:1,param2[1,2]}")
显然,前面的示例将不会通过,因为我们使用了相同的规则,在第二个测试中有一个not (!)。这将导致(true && !true)或(false && !false)评估。
如果您想进行OR检查,可以将此放入第二个数组中
array(array("toto{param1:1,param2[1,2]}","!toto{param1:1,param2[1,2]}"))
在这种情况下,最终结果总是返回true,因为评估将是((true || !true)或((false || !false)))
您可以混合这些
array(rule1{},array(rule2{},rule3{}))
这将导致($rule1Result && ($rule2Result || $rule3Result))
该系统灵感来源于Symfony 1凭证检查https://symfony.com.cn/legacy/doc/reference/1_4/en/08-Security和规范模式http://en.wikipedia.org/wiki/Specification_pattern
查看单元测试以获取更多使用示例。
实际应用
以下是一些实际应用中的示例。此库中不提供规则的类实现,该库只是引擎本身。
安全性
检查基于可以提供权限列表的对象的一些复杂权限规则
$businessRuleEngine->check(array("permission{name:user}","!permission{name:newUser}"),array($user));//user && !newUser $businessRuleEngine->check(array(array("permission{name:admin}","permission{name:moderator}")),array($user));// admin || moderator
支付方式
根据某些订单属性检查要提供的支付方式
$paymentMethodName = $businessRuleEngine->getFirstMatch( array( "cheapCharge" => array("orderCountry{countries:[CA,US]}","maxOrderPrice{max:9.99}"), "digitalProduct" => array("!orderContainPhysical"), "fallback" => array() ), $order )
扑克牌游戏
基于具有最大价值的牌手。这不是完整的,但展示了其可能的用途
$rules = array( array("cardsValues{values:[10,11,12,13,A]}","cardsSameColor"), array("cardsStraight","cardsSameColor"), array("cardsSameValue{amountOfCards:[4]}"), array("cardsSameValue{amountOfCards:[3,2]"), array("cardsSameColor"), array("cardsStraight"), array("cardsSameValue{amountOfCards:[3]"), array("cardsSameValue{amountOfCards:[2,2]"), array("cardsSameValue{amountOfCards:[2]"), array(), ); $positionHand1 = $businessRuleEngine->getFirstMatch($rules,$hand1); $positionHand2 = $businessRuleEngine->getFirstMatch($rules,$hand2); if($positionHand1 == $positionHand2) { if($businessRuleEngine->check('firstHandHighestCardValue',array('hand1'=>$hand1,'hand2'=>$hand2))) { $winner = 'hand1'; } else { $winner = 'hand2'; } } else { $winner = $positionHand1 < $positionHand2 ? 'hand1' : 'hand2'; }
促销显示
如果您根据用户显示促销。完全是虚构的规则...
$businessRuleEngine->check( array('lastTransaction{delay: - 1 months}','lastVisit{delay: -5 days}',array('totalPurchaseLessThan{amount:20.95}','fromCountry{countries[CA,US]}')), $user );
这意味着如果
用户的最后交易在1个月前完成
AND
用户的最后访问在5天前完成
AND
(用户的总购买少于20.95美元)
OR
来自国家列表中的CA和US)