Rule Engine Documentation
Overview
The Rule Engine is a flexible and extensible framework for defining and evaluating rules and conditions, and executing corresponding actions based on specified conditions. This documentation provides detailed information on how to configure, use, and extend the Rule Engine.
Getting Started
To get started with the Rule Engine:
-
Install the library into your project.
-
Define your rules using a structured array configuration.
-
Use the
ArrayBuilder
class to build aRuleSet
. -
Execute the rules with a provided context.
For more detailed installation instructions, see the Installation page.
Key Concepts
Conditions
Conditions define logical checks to evaluate data within a given context. Examples of conditions include:
- Checking if a number is greater than or equal to a specific value.
- Verifying if a string starts with a given prefix.
- Checking if an array contains a specific value.
The Rule Engine provides a variety of built-in conditions:
EqualsCondition
: Checks if a value equals another valueGreaterThanCondition
: Checks if a value is greater than another valueLessThanCondition
: Checks if a value is less than another valueGreaterThanOrEqualCondition
: Checks if a value is greater than or equal to another valueLessThanOrEqualCondition
: Checks if a value is less than or equal to another valueStartsWithCondition
: Checks if a string starts with a specific prefixEndsWithCondition
: Checks if a string ends with a specific suffixStringContainCondition
: Checks if a string contains a specific substringArrayContainsCondition
: Checks if an array contains a specific valueArrayContainsAllCondition
: Checks if an array contains all specified valuesArrayContainsAnyCondition
: Checks if an array contains any of the specified valuesNumericInRangeCondition
: Checks if a number is within a specified rangeNotCondition
: Negates the result of another conditionCollectionCondition
: Combines multiple conditions with logical operators (AND, OR)
Actions
Actions define the operations to be executed when conditions are met or not met. Examples include:
- Triggering a custom function or callback.
- Updating a database field.
- Sending notifications.
The Rule Engine provides a CallableAction
that allows you to use any callable function as an action.
Rule Structure
Rules consist of conditions and actions. The condition specifies the logic to be evaluated, while actions define what should happen based on the result of the evaluation.
Node Types
The Rule Engine supports the following node types:
condition
: Represents a conditional logic node.collection
: A group of conditions evaluated with logical operators (and
,or
).context
: A condition that retrieves a value from the context and evaluates it using an operator.not
: Negates the result of a condition.action
: Represents an action to execute.
Example Rule Configuration
Below is a comprehensive example of a rule configuration:
$config = [
'node' => 'condition',
'if' => [
'node' => 'collection',
'type' => 'and',
'nodes' => [
[
'node' => 'context',
'contextName' => 'depositCount',
'operator' => 'greaterThanOrEqual',
'value' => 2,
],
[
'node' => 'context',
'contextName' => 'accountAge',
'operator' => 'greaterThanOrEqual',
'value' => 1,
],
[
'node' => 'collection',
'type' => 'or',
'nodes' => [
[
'node' => 'context',
'contextName' => 'hasVipStatus',
'operator' => 'equal',
'value' => true,
],
[
'node' => 'not',
'condition' => [
'node' => 'collection',
'type' => 'or',
'nodes' => [
[
'node' => 'context',
'contextName' => 'hasVipStatus',
'operator' => 'equal',
'value' => true,
],
[
'node' => 'not',
'condition' => [
'node' => 'context',
'contextName' => 'withdrawalCount',
'operator' => 'lessThanOrEqual',
'value' => 1,
],
],
],
],
],
],
],
],
],
'then' => [
'node' => 'action',
'actionName' => 'actionName1',
'arguments' => [
'param1' => 'arg1',
'param2' => 'arg2',
],
],
'else' => [
'node' => 'action',
'actionName' => 'actionName2',
],
];
Configuration and Usage
Building a RuleSet
- Define your rule configuration: Use the structure described above to define your rules.
-
Build the RuleSet:
use Maniaba\RuleEngine\Builders\ArrayBuilder; $builder = new ArrayBuilder(); $ruleSet = $builder->build($config);
-
Execute the RuleSet:
use Maniaba\RuleEngine\Context\ArrayContext; $context = new ArrayContext([ 'depositCount' => 3, 'accountAge' => 2, 'hasVipStatus' => true, 'withdrawalCount' => 0, ]); // Create an evaluator $evaluator = new Maniaba\RuleEngine\Evaluators\BasicEvaluator(); // Execute the rule set $evaluator->execute(clone $ruleSet, $context);
Customizing Actions
Actions can be customized using the ActionFactory
class. Arguments can be passed from the configuration.
For more detailed usage instructions, see the Basic Usage and Advanced Usage pages.
Advanced Topics
Custom Conditions
You can create custom conditions by implementing the ConditionInterface
. For example:
final class CustomCondition implements ConditionInterface
{
public function __construct(private string $contextName, private mixed $expectedValue) {}
public static function factory(array $data): ConditionInterface
{
return new self($data['contextName'], $data['expectedValue']);
}
public function isSatisfied(ArrayContext $context): bool
{
return $context->getField($this->contextName) === $this->expectedValue;
}
public function getFailureMessage(): array|string|null
{
return "Custom condition failed";
}
}
Custom Actions
Custom actions can be implemented by extending the ActionInterface
. For example:
final class NotifyAction implements ActionInterface
{
public function execute(ArrayContext $context, string $message = '', string $channel = 'email'): bool
{
echo "Notification sent to {$channel} with message: {$message}";
return true;
}
}
Best Practices
- Keep configurations modular: Break down complex rules into smaller, manageable configurations.
- Use meaningful action names: Ensure action names clearly describe their purpose.
- Validate configurations: Use validation utilities to check the structure of your rule configurations.
- Handle errors gracefully: Check for execution errors after running rules.
- Use appropriate context types: Choose between
ArrayContext
andObjectContext
based on your data structure.
Frequently Asked Questions (FAQ)
Q: Can I nest conditions?
A: Yes, conditions can be nested using the collection
or not
nodes.
Q: How do I debug failing conditions?
A: Use the getFailureMessage
method provided by conditions to understand why a condition failed.
Q: Can I reuse conditions or actions across multiple rules?
A: Yes, you can reuse condition and action definitions as long as the logic aligns.
Q: How do I prioritize rules?
A: Use the setPriority
method on rules to set their priority. Rules with higher priority values will be executed first.
Conclusion
The Rule Engine is a powerful tool for building dynamic, extensible rule-based systems. By following this documentation, you can configure and execute rules tailored to your application's requirements. For further customization, extend the provided interfaces to create new conditions and actions.