uuf6429 / rune
PHP 规则引擎。
3.0-RC1
2023-10-28 17:52 UTC
Requires
- php: ^7.4 || ^8
- phpdocumentor/reflection-docblock: ^5.3
- symfony/expression-language: ^4 || ^5 || ^6
Requires (Dev)
- ext-json: *
- friendsofphp/php-cs-fixer: ^3
- jetbrains/phpstorm-attributes: ^1.0
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^6 || ^9
This package is auto-updated.
Last update: 2024-09-03 07:36:59 UTC
README
Rune - PHP Rule Engine 工具包。
这个库是实现 业务规则引擎(一种业务流程自动化软件)的。
目录
安装
推荐且最简单的安装 Rune 的方式是通过 Composer
composer require uuf6429/rune
架构
该库由以下主要部分组成
- 规则(实现
Rule\RuleInterface
) - 表示业务规则的对象。对于大多数用例,可以使用Rule\GenericRule
。每个规则必须有一个唯一的 id、描述性名称、条件(作为一个返回true
或false
的表达式)和当条件满足时触发的操作(见下文)。 - 操作(实现
Action\ActionInterface
) - 当相关规则被触发时执行某些操作的对象。一般来说,操作可以被多个规则重用。例如,如果您在产品销售中使用规则引擎,则操作可能会在满足某些条件时自动向账单添加费用(例如,针对特定配送国家的费用,或针对折扣的负费用)。 - 上下文(实现
Context\ContextInterface
) - 为规则引擎和操作提供数据以进行工作的对象。这可以被视为当前情况所有可用数据的一个集合。例如,当当前情况是关于用户购买产品时,您将拥有有关用户、产品、优惠的数据,也许还有时间、地区等高级信息。几乎总是需要实现自己的上下文,因为这总是取决于您的(业务)场景。 - RuleEngine - 实质上,连接其他部分以使其工作的对象。
使用方法
可以在 uuf6429/rune-examples 找到各种示例。
实时示例
示例代码
以下代码是 Rune 可以如何使用的非常简单的示例。它定义了一个模型(Product
)、上下文(ProductContext
),并使用 CallbackAction
打印出已触发的规则。
namespace MyApplication; use uuf6429\Rune\Action\CallbackAction; use uuf6429\Rune\Context\ClassContext; use uuf6429\Rune\Engine; use uuf6429\Rune\Rule\GenericRule; use uuf6429\Rune\Rule\RuleInterface; // A class whose instances will be available inside the rule engine. class Product { public function __construct( public readonly string $name, public readonly string $colour, ) { } } // A class that represents the rule engine execution context. // Note that public properties will be available in the rule expressions, // in this case rules will have access to "product" as a variable (and all of product's public properties). class ProductContext extends ClassContext { public function __construct( public readonly Product $product ) { } } // Declare an action to be triggered when a rule matches against a product. $action = new CallbackAction( static fn ($eval, ProductContext $context, RuleInterface $rule) => printf( "Rule %s triggered for %s %s\n", $rule->getId(), ucwords($context->product->colour), $context->product->name ) ); // Declare some sample rules. $rules = [ new GenericRule(1, 'Red Products', 'product.colour == "red"', $action), new GenericRule(2, 'Red Socks', 'product.colour == "red" and product.name matches "/socks/i"', $action), new GenericRule(3, 'Green Socks', 'product.colour == "green" and product.name matches "/socks/i"', $action), new GenericRule(4, 'Socks', 'product.name matches "/socks/" > 0', $action), ]; // Declare available products (to run rules against). $products = [ new Product('Bricks', 'red'), new Product('Soft Socks', 'green'), new Product('Sporty Socks', 'yellow'), ]; // Create rule engine. $engine = new Engine(); // Run rules for each product. Note that each product should exist in a separate context. foreach ($products as $product) { $engine->execute(new ProductContext($product), $rules); }