zitec / rule-engine-bundle
Requires
- php: >=7.1
- symfony/symfony: ~3.0
Suggests
- doctrine/orm: For using Rule entities
- sonata-project/doctrine-orm-admin-bundle: For easy administration of the doctrine entities.
This package is not auto-updated.
Last update: 2024-09-15 02:52:15 UTC
README
规则引擎是一个symfony包,允许您使用自定义参数和评估器构建复杂的条件集,以匹配您的对象和需求。它提供了一个友好的前端界面,并且可以简单集成Doctrine实体及其相应的Sonata管理员。有一个演示网站吗?
安装
您可以通过composer安装它。
{ "require":{ "zitec/rule-engine-bundle": "~1.0" } }
用法
如何使用
上下文对象
编写一个实现RuleContextInterface的类,并添加一些方法,这些方法将返回您希望在规则中包含的参数。为了使事情更加简单,已经存在一个基本上下文类:ContextBase。它已经为current_date、current_day和current_time这三个参数提供了getter。您的自定义上下文可以扩展这个。
namespace MyBundle/RuleEngine/Context; use Zitec/RuleEngineBundle/Service/ContextBase; class MyFirstContext extends ContextBase { protected $dataSource; // Using a custom name will help you identify the context in built expressions. public function getContextObjectKey(): string { return 'my-name'; } // The context will need a data source to read from. We will set the data source when we evaluate the expression. public function setMyDataSource($dataSource) { $this->dataSource = $dataSource; } // Added a parameter. public function getMyParameter(): string { return $this->dataSource->getTheData(); } }
条件
对于上下文对象中的每个参数(方法),创建一个Condition对象。支持ContextBase类中的三个日期时间参数的条件服务已经在规则引擎包中定义。我们将在新的包中为新增的参数(my_parameter)添加另一个。我们可以从头开始编写条件,但扩展两个提供对单值和数组参数基本运算符支持的两个Abstract条件类会更简单。如果“my_parameter”实际上是一个数组,我们可以这样做
namespace MyBundle/RuleEngine/Conditions; use Zitec/RuleEngineBundle/Conditions/AbstractArrayCondition; class MyParameter extends AbstractArrayCondition { // When we ask the context object for the method for this condition name, // it should respond with getMyCondition, since the ContextBase does simple snake_case to getCamelCase. protected $name = 'my_parameter'; // This is the name the users will see in admin pages. protected $label = 'My Parameter'; // A help text displayed in the condition builder if the user selects this parameter. protected $description = 'Set conditions for my parameter'; // Here is where we decide on the operators that will be available for this parameter. protected function getOperatorDefinitions(): array { $options = [ ['key' => 'one', 'label' => 'Option one'], ['key' => 'two', 'label' => 'Option two'], ]; // Details about the operator definition structure can be found in the Operator definition section. return [ [ 'label' => 'match ANY of the following', 'name' => $this::INTERSECTING, 'fieldType' => 'select', 'fieldOptions' => [ 'multiple' => true, 'options' => $options, ], ], [ 'label' => 'match NONE of the following', 'name' => $this::DISJOINT, // Details about the autocomplete feature in the Autocomplete section of this readme. 'fieldType' => 'autocomplete', 'fieldOptions' => [ 'autocomplete' => 'my_autocomplete_key', ], ], ]; } }
规则管理器服务
现在我们有了上下文对象和匹配的定义,让我们使用RuleConditionsManager创建一个服务。我们需要将您的上下文对象作为参数传递,并将条件作为‘addSupportedCondition’调用。由于我们扩展了ContextBase类,我们可以使用规则引擎定义的日期时间条件。以下是使用上述类定义的服务的示例。
my_bundle.rule_engine.context.my_first_context: class: MyBundle\RuleEngine\Context\MyFirstContext shared: false my_bundle.rule_engine.condition.my_parameter: class: MyBundle\RuleEngine\Conditions\MyParameter public: false my_bundle.rule_engine.manager.my_object: class: Zitec\RuleEngineBundle\Service\RuleConditionsManager arguments: ['@my_bundle.rule_engine.context.my_first_context'] calls: - [addSupportedCondition, ["@rule_engine.condition.current_date"]] - [addSupportedCondition, ["@rule_engine.condition.current_day"]] - [addSupportedCondition, ["@rule_engine.condition.current_time"]] - [addSupportedCondition, ["@my_bundle.rule_engine.condition.my_parameter"]]
表单构建
现在我们需要使用上下文和条件来渲染前端条件构建器。这可以通过向表单添加RuleEngineType表单类型并在字段选项中将规则管理器服务设置为'rule_manager'键来完成。
但在大多数情况下,您想要与规则关联的操作可能需要自己的数据。例如,我们可能决定根据我们的对象中的参数向不同的地址发送电子邮件。在这种情况下,我们可以定义一个包含电子邮件字段的doctrine实体来定义地址,并将其设置为规则实体。这样做很简单:只需在您的类中添加"implements RuleInterface",并添加"use RuleTrait"语句来实际实现接口。
class EmailAddress implements RuleInterface { use RuleTrait; // Your entity's properties and getters/setters follow. }
更新doctrine模式并注意与Rule实体的新关系,该实体将保存EmailAddress实体的表达式。
您的规则集成实体需要与一个上下文和条件集关联,即规则条件管理器。为此,您必须向条件管理器服务声明中添加一个标签。上述服务变为
my_bundle.rule_engine.manager.my_object: class: Zitec\RuleEngineBundle\Service\RuleConditionsManager arguments: ['@my_bundle.rule_engine.context.my_first_context'] calls: - [addSupportedCondition, ["@rule_engine.condition.current_date"]] - [addSupportedCondition, ["@rule_engine.condition.current_day"]] - [addSupportedCondition, ["@rule_engine.condition.current_time"]] - [addSupportedCondition, ["@my_bundle.rule_engine.condition.my_parameter"]] tags: - { name: rule_engine.conditions_manager, entity: "MyBundle:EmailAddress" }
接下来是管理部分。
我将假设您正在使用SonataAdmin来管理您的doctrine实体。如果是这样,这是您需要做的事情
在Admin类中,添加一个"use RuleAdminTrait"语句,并使用相关方法
class EmailAddressAdmin extends AbstractAdmin { use RuleAdminTrait; protected function configureFormFields(FormMapper $formMapper) { // Add the rule admin, using the method from the trait: $this->addRuleFormElement($formMapper); // Add the rest of your fields. } protected function configureListFields(ListMapper $list) { // Add the columns from the rule entity. On dev environments, the generated espression will also be visible. $this->addRuleListColumns($list); // Add the rest of your columns and actions. }
恭喜!您现在可以看到了它的实际效果,并可以使用复杂的规则设置各种地址!
规则评估
在您的业务流程的某个地方,您将需要提取与您的对象匹配的电子邮件地址(们)。为此的代码将使用RuleEvaluator服务,可能看起来像这样
use Doctrine\ORM\EntityRepository; use MyBundle\RuleEngine\Context\MyFirstContext; use Zitec\RuleEngineBundle\Service\RuleEvaluator; class RecipientChooserService { /** * The entity repository for your EmailAddress entity * @var EntityRepository */ protected $emailAddressRepository; /** * @var RuleEvaluator */ protected $evaluator; /** * @var MyFirstContext */ protected $context; public function __construct( EntityRepository $emailAddressRepository, RuleEvaluator $evaluator, MyFirstContext $context ) { $this->emailAddressRepository = $emailAddressRepository; $this->evaluator = $evaluator; $this->context = $context; } public function getRecipientAddresses($myDataSource) { // Load and filter email addresses. $this->context->setMyDataSource($myDataSource); /** @var EmailAddress[] $emailAddresses */ $emailAddresses = $this->emailAddressRepository->findAll(); // Determine the applicable addresses. $recipients = []; foreach ($emailAddresses as $entity) { if ($this->evaluator->evaluate($entity->getRule(), $this->context)) { $recipients[] = $entity->getEmail(); } } return $recipients; } }
就这样!完成了!
其他文档
运算符定义
操作符是一个具有以下键的数组
- name(必填):机器名称,用于在条件中识别选定的操作符
- label(必填):用户在管理页面中看到的文本
- fieldType(必填):请参见下面的可能值
- fieldOptions(可选):请参见以下详情
- value_transform(可选):应用于从规则构建器接收的值并在生成表达式之前的回调
- value_view_transform(可选):应用于从规则构建器接收的值并在生成规则管理视图之前的回调
字段类型和选项
- text:基本文本输入,适用于具有自由格式值的单值参数。
- datetime:日期选择器输入;将您的日期选择器选项添加到fieldOptions数组中的datetimepicker键。
- interval:基本间隔定义,具有用于“从”和“到”值的文本输入。
- datetime_interval:结合上述两种类型,就有了带有日期选择器的间隔。
- select:一个增强的select2选择框;您可以在MyParameter条件声明中看到一个实现。
- autocomplete:一个使用RuleEngine自动完成功能的自动完成的select2输入。
自动完成支持
为了使用自动完成字段,您需要通过实现Zitec\RuleEngineBundle\Autocomplete\AutocompleteInterface来定义一个数据源。如果您想对Doctrine实体进行自动完成,可以扩展AbstractAutocompleteEntity类
use MyBundle\Entity\MyEntity; use Zitec\RuleEngineBundle\Autocomplete\AbstractAutocompleteEntity; class MyEntityAutocomplete extends AbstractAutocompleteEntity { protected function getEntityClass(): string { return MyEntity::class; } protected function getIdField(): string { return 'id'; // This will be the value used in the built expression } protected function getTextField(): string { return 'name'; // This will be the value displayed to the user. } }
并使用“rule_engine.autocomplete.data_source”标签声明服务
my_bundle.rule_engine.autocomplete.my_autocomplete: class: MyBundle\RuleEngine\Autocomplete\MyEntityAutocomplete arguments: ["@doctrine.orm.default_entity_manager"] tags: - { name: rule_engine.autocomplete.data_source, key: my_autocomplete_key }
键的值是您必须在自动完成类型中用于fieldOptions的值。
别忘了将路由信息添加到您应用的routing.yml文件中
rule_engine: resource: "@ZitecRuleEngineBundle/Resources/config/routing.yml" prefix: /