1. Go to this page and download the library: Download leeovery/rules-engine library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
leeovery / rules-engine example snippets
use LeeOvery\RulesEngine\Condition;
use LeeOvery\RulesEngine\Facades\RulesEngine;
// Publish version 1 of a rule set.
RulesEngine::ruleSet('merchant-categories')
->rule('tesco', Condition::whereStartsWith('merchant', 'TESCO'), 'groceries')
->rule('shell', Condition::whereStartsWith('merchant', 'SHELL'), 'fuel')
->rule('fallback', Condition::always(), 'uncategorised')
->publish();
// Resolve it against facts.
RulesEngine::for('merchant-categories')
->with(['merchant' => 'TESCO STORES 3021'])
->firstValue(); // 'groceries'
// Add a rule. This publishes version 2, and version 1 stays as it was.
RulesEngine::ruleSet('merchant-categories')
->addRule('pret', Condition::whereContains('merchant', 'PRET'), 'eating-out', before: 'fallback')
->publish();
enum RuleSet: string
{
case MerchantCategories = 'merchant-categories';
}
enum Category: string
{
case Groceries = 'groceries';
case Fuel = 'fuel';
case EatingOut = 'eating-out';
case Uncategorised = 'uncategorised';
}
use LeeOvery\RulesEngine\Condition;
use LeeOvery\RulesEngine\Facades\RulesEngine;
RulesEngine::ruleSet(RuleSet::MerchantCategories)
->description('Spending categories by merchant')
->rule('tesco', Condition::whereStartsWith('merchant', 'TESCO'), Category::Groceries)
->rule('shell', Condition::whereStartsWith('merchant', 'SHELL'), Category::Fuel)
->rule('pret', Condition::whereContains('merchant', 'PRET'), Category::EatingOut)
->rule('fallback', Condition::always(), Category::Uncategorised)
->publishedBy('alex')
->note('Starting categories')
->publish();
$match->ruleSet; // 'merchant-categories'
$match->version; // 1
$match->versionId; // the rule_set_versions id
$match->ruleId; // the rules id
$match->uuid; // the rule's permanent uuid
$match->key; // 'tesco'
$match->position; // 1
$match->value; // 'groceries', decoded from JSON
$match->score; // 1
$match->metadata(); // all metadata, or null
$match->metadata('source.answer'); // a key, with dot notation
$match->metadata('owner', 'unknown'); // with a default
$match->as(Category::class); // the enum case for the value
$preview = RulesEngine::ruleSet(RuleSet::MerchantCategories)
->addRule('costa', Condition::whereContains('merchant', 'COSTA'), Category::EatingOut)
->preview();
$preview->version; // the number it would get
$preview->previousVersion; // the version it's compared with
$preview->rules; // the complete rule list, as RuleDefinition values with keys and uuids
$preview->changes; // the RuleSetChanges it would make
RulesEngine::ruleSet(RuleSet::MerchantCategories)
->publishedBy('alex')
->note('Back to the starting categories')
->revertTo(1);
$changes = RulesEngine::changes(RuleSet::MerchantCategories, from: 1, to: 3);
$changes->added; // RuleReference values, each with a uuid and key
$changes->removed;
$changes->renamed; // RenamedRule values, each with a uuid, from and to
$changes->conditionChanged;
$changes->valueChanged;
$changes->metadataChanged;
$changes->moved;
$changes->isEmpty();
RulesEngine::for(RuleSet::MerchantCategories)
->asOf($transaction->booked_on) // the version in force on that date
->knownAt($transaction->categorised_at) // only versions published by then
->with(['merchant' => $transaction->merchant])
->first();
use Illuminate\Support\Facades\Event;
use LeeOvery\RulesEngine\Events\RuleSetVersionPublished;
Event::listen(function (RuleSetVersionPublished $event): void {
foreach ($event->changes->valueChanged as $rule) {
// re-categorise the transactions that $rule->uuid answered
}
});
use LeeOvery\RulesEngine\Operator;
// Equals (default operator)
Condition::where('merchant', 'TESCO')
// With an explicit operator, as a string or an Operator case
Condition::where('amount', '>', 10000)
Condition::where('amount', Operator::GreaterThan, 10000)
// AND and OR
Condition::whereStartsWith('merchant', 'SHELL')->where('amount', '<', 2000)
Condition::whereContains('merchant', 'PRET')->orWhereContains('merchant', 'COSTA')
// Nested: type = 'card' AND (country = 'UK' OR country = 'IE')
Condition::where('type', 'card')
->where(fn ($q) => $q->where('country', 'UK')->orWhere('country', 'IE'))
Condition::whereIn('status', ['pending', 'booked'])
Condition::whereNotIn('type', ['refund', 'fee'])
Condition::whereNot('archived', true)
Condition::whereNull('merchant')
Condition::whereNotNull('merchant')
Condition::whereContains('merchant', 'PRET')
Condition::whereStartsWith('merchant', 'TESCO')
Condition::whereEndsWith('merchant', 'LTD')
// Every method has an 'or' variant
Condition::where('a', 1)->orWhereIn('b', [2, 3])
Condition::always() // matches any facts
Condition::else() // the same, reads well as a last rule
RulesEngine::versions(RuleSet::MerchantCategories); // every RuleSetVersion, oldest first
RulesEngine::versions(RuleSet::MerchantCategories)->load('rules');
RulesEngine::version(RuleSet::MerchantCategories, 2); // one version; its rules load on access
RulesEngine::newestVersion(RuleSet::MerchantCategories); // the version published last, whatever its effective date
RulesEngine::changes(RuleSet::MerchantCategories, from: 1, to: 2); // what changed between them