cleverage/Ruler is a PHP 5.3 Library. Use it to implement your own business rules, and link them in order to check if you are satisfying the set.
Exemple :
You want to check if the current user can activate a feature. For this, you have to check that :
- he is connected,
- he has the premium suscription,
- he has enough money in his account.
<?php// test// PHP 5.3$rule = newIsConnectedRule($user);
$rule->andRule(newIsSuscriberRule($user, 'PREMIUM'))
->andRule(newHasMoneyRule($user, 300))
->orRule(newIsAdminRule($user));
// PHP 5.4$rule = (newIsConnectedRule($user))
->andRule(newIsSuscriberRule($user, 'PREMIUM'))
->andRule(newHasMoneyRule($user, 300))
->orRule(newIsAdminRule($user));
try {
if ($rule->isSatisfied()) {
echo'activated';
}
} catch (NotConnectedException$e) {
// show connection form
} catch (NotSuscriberException$e) {
// show subscription form
} catch (NotEnoughMoneyException$e) {
echo'not enough Money';
} catch(\CleverAge\Ruler\Exception\Exception$e) {
echo'Failed : '.$e->getMessage();
}<?php// IsConnectedRule classclass IsConnectedRule extends \CleverAge\Ruler\RuleAbstract
{
protected$_user;
protected$_failure_exception_class = 'NotConnectedException';
protected$_failure_message = 'user is not connected';
publicfunction__construct(\User$user)
{
$this->_user = $user;
}
publicfunctiondoIsSatisfied()
{
return$this->_user->isLoggedOn();
}
}Combination of rules can even be done in a single rule class, in order to simplify your application code and increase maintability.
// ActiveFeatureXRule classclass ActiveFeatureXRule extends \CleverAge\Ruler\RuleAbstract
{
publicfunction__construct(\User$user)
{
$this->andRule(newIsSuscriberRule($user, 'PREMIUM'))
->andRule(newHasMoneyRule($user, 300))
->orRule(newIsAdminRule($user));
}
publicfunctiondoIsSatisfied()
{
// method is abstract, and this container rule always satisfies.returntrue;
}
}Now, you can use this rule class everywhere you need it, and just change the construct to have th rules reverberated everewhere.
The order in which you set OR/AND/NAND rules is not important. At the end, they are grouped by type.
- You want your ruleset satisfied :
// A,B,C,D,G,Z are rules$A->andRule($B)
->orRule($C->andRule($Z))
->andRule($D)
->nandRule($G)
->isSatisfied();
// PHP =>($A && $B && $D && !$G) || ($C && $Z)// Binary => (A.B.D.!G)+(C.Z)- You want your ruleset not satisfied :
// A,B,C,D,G,Z are rules$A->andRule($B)
->orRule($C->andRule($Z))
->andRule($D)
->nandRule($G)
->isNotSatisfied()
// PHP => (!$A || !$B || !$D || $G) && (!$C || !$Z)// Binary => (!A+!B+!D+G).(!C+!Z)by default, isNotSatisfied() returns !isSatisfied(). But sometimes, you may want to personnalize the doIsNotSatisfied() method in order to optimize workflow (like SQL queries).
If you have one generic rule (e.g. : ObjectIsEqual), you may need to have different exception thrown when composing complex rules. Each Rule has a setter for this :
$A = newMyRule();
$A->setException('My\Name\Space\Ruler\Exceptions\MyException', 'my custom error message');
$A->isSatisfied();
// If rule is not satisfied// it throws a new My\Name\Space\Ruler\Exceptions\MyException('my custom error message') exception