1. Go to this page and download the library: Download ruler/ruler 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/ */
$actualNumPeople = new Variable('actualNumPeople');
$rule = new Rule(
new Operator\LogicalAnd([
new Operator\LessThanOrEqualTo(new Variable('minNumPeople'), $actualNumPeople),
new Operator\GreaterThanOrEqualTo(new Variable('maxNumPeople'), $actualNumPeople)
]),
function() {
echo 'YAY!';
}
);
$context = new Context([
'minNumPeople' => 5,
'maxNumPeople' => 25,
'actualNumPeople' => fn() => 6,
]);
$rule->execute($context); // "Yay!"
// These are Variables. They'll be replaced by terminal values during Rule evaluation.
$a = $rb['a'];
$b = $rb['b'];
// Here are bunch of Propositions. They're not too useful by themselves, but they
// are the building blocks of Rules, so you'll need 'em in a bit.
$a->greaterThan($b); // true if $a > $b
$a->greaterThanOrEqualTo($b); // true if $a >= $b
$a->lessThan($b); // true if $a < $b
$a->lessThanOrEqualTo($b); // true if $a <= $b
$a->equalTo($b); // true if $a == $b
$a->notEqualTo($b); // true if $a != $b
$a->stringContains($b); // true if strpos($b, $a) !== false
$a->stringDoesNotContain($b); // true if strpos($b, $a) === false
$a->stringContainsInsensitive($b); // true if stripos($b, $a) !== false
$a->stringDoesNotContainInsensitive($b); // true if stripos($b, $a) === false
$a->startsWith($b); // true if strpos($b, $a) === 0
$a->startsWithInsensitive($b); // true if stripos($b, $a) === 0
$a->endsWith($b); // true if strpos($b, $a) === len($a) - len($b)
$a->endsWithInsensitive($b); // true if stripos($b, $a) === len($a) - len($b)
$a->sameAs($b); // true if $a === $b
$a->notSameAs($b); // true if $a !== $b
$c = $rb['c'];
$d = $rb['d'];
// Mathematical operators are a bit different. They're not Propositions, so
// they don't belong in rules all by themselves, but they can be combined
// with Propositions for great justice.
$rb['price']
->add($rb['shipping'])
->greaterThanOrEqualTo(50)
// Of course, there are more.
$c->add($d); // $c + $d
$c->subtract($d); // $c - $d
$c->multiply($d); // $c * $d
$c->divide($d); // $c / $d
$c->modulo($d); // $c % $d
$c->exponentiate($d); // $c ** $d
$c->negate(); // -$c
$c->ceil(); // ceil($c)
$c->floor(); // floor($c)
$e = $rb['e']; // These should both be arrays
$f = $rb['f'];
// Manipulate sets with set operators
$e->union($f);
$e->intersect($f);
$e->complement($f);
$e->symmetricDifference($f);
$e->min();
$e->max();
// And use set Propositions to
// Create a Rule with an $a == $b condition
$aEqualsB = $rb->create($a->equalTo($b));
// Create another Rule with an $a != $b condition
$aDoesNotEqualB = $rb->create($a->notEqualTo($b));
// Now combine them for a tautology!
// (Because Rules are also Propositions, they can be combined to make MEGARULES)
$eitherOne = $rb->create($rb->logicalOr($aEqualsB, $aDoesNotEqualB));
// Just to mix things up, we'll populate our evaluation context with completely
// random values...
$context = new Context([
'a' => rand(),
'b' => rand(),
]);
// Hint: this is always true!
$eitherOne->evaluate($context);
$rb->logicalNot($aEqualsB); // The same as $aDoesNotEqualB :)
$rb->logicalAnd($aEqualsB, $aDoesNotEqualB); // True if both conditions are true
$rb->logicalOr($aEqualsB, $aDoesNotEqualB); // True if either condition is true
$rb->logicalXor($aEqualsB, $aDoesNotEqualB); // True if only one condition is true
$context = new Context([
'userName' => fn() => $_SESSION['userName'] ?? null,
]);
$userIsLoggedIn = $rb->create($rb['userName']->notEqualTo(null));
if ($userIsLoggedIn->evaluate($context)) {
// Do something special for logged in users!
}
$hiJon = $rb->create(
$rb['userName']->equalTo('jwage'),
function() {
echo "Hey there Jon!";
}
);
$hiEveryoneElse = $rb->create(
$rb->logicalAnd(
$rb->logicalNot($rb->logicalOr($hiJustin, $hiJon)), // The user is neither Justin nor Jon
$userIsLoggedIn // ... but a user nonetheless
),
function() use ($context) {
echo sprintf("Hello, %s", $context['userName']);
}
);
$rules = new RuleSet([$hiJustin, $hiJon, $hiEveryoneElse]);
// Let's add one more Rule, so non-authenticated users have a chance to log in
$redirectForAuthentication = $rb->create($rb->logicalNot($userIsLoggedIn), function() {
header('Location: /login');
exit;
});
$rules->addRule($redirectForAuthentication);
// Now execute() all true Rules.
//
// Astute readers will note that the Rules we defined are mutually exclusive, so
// at most one of them will evaluate to true and execute an action...
$rules->executeRules($context);
$context = new Context;
// Some static values...
$context['reallyAnnoyingUsers'] = ['bobthecow', 'jwage'];
// You'll remember this one from before
$context['userName'] = fn() => $_SESSION['userName'] ?? null;
// Let's pretend you have an EntityManager named `$em`...
$context['user'] = function() use ($em, $context) {
if ($userName = $context['userName']) {
return $em->getRepository('Users')->findByUserName($userName);
}
};
$context['orderCount'] = function() use ($em, $context) {
if ($user = $context['user']) {
return $em->getRepository('Orders')->findByUser($user)->count();
}
return 0;
};
// Reusing our $context from the last example...
// We'll define a few context variables for determining what roles a user has,
// and their full name:
$context['userRoles'] = function() use ($em, $context) {
if ($user = $context['user']) {
return $user->roles();
} else {
// return a default "anonymous" role if there is no current user
return ['anonymous'];
}
};
$context['userFullName'] = function() use ($em, $context) {
if ($user = $context['user']) {
return $user->fullName;
}
};
// Now we'll create a rule to write the log message
$rb->create(
$rb->logicalAnd(
$userIsLoggedIn,
$rb['userRoles']->contains('admin')
),
function() use ($context, $logger) {
$logger->info(sprintf("Admin user %s did a thing!", $context['userFullName']));
}
);
// We can skip over the Context Variable building above. We'll simply set our,
// default roles on the VariableProperty itself, then go right to writing rules:
$rb['user']['roles'] = ['anonymous'];
$rb->create(
$rb->logicalAnd(
$userIsLoggedIn,
$rb['user']['roles']->contains('admin')
),
function() use ($context, $logger) {
$logger->info(sprintf("Admin user %s did a thing!", $context['user']['fullName']);
}
);
namespace My\Ruler\Operators;
use Ruler\Context;
use Ruler\Operator\VariableOperator;
use Ruler\Proposition;
use Ruler\Value;
class ALotGreaterThan extends VariableOperator implements Proposition
{
public function evaluate(Context $context): bool
{
list($left, $right) = $this->getOperands();
$value = $right->prepareValue($context)->getValue() * 10;
return $left->prepareValue($context)->greaterThan(new Value($value));
}
protected function getOperandCardinality()
{
return static::BINARY;
}
}