2017 © Pedro Peláez
 

library rules

Nested rules with php

image

dnoegel/rules

Nested rules with php

  • Monday, February 23, 2015
  • by dnoegel
  • Repository
  • 1 Watchers
  • 1 Stars
  • 2 Installations
  • PHP
  • 0 Dependents
  • 0 Suggesters
  • 1 Forks
  • 1 Open issues
  • 1 Versions
  • 0 % Grown

The README.md

Rules

'Rules' is a simple PHP library which allows you to check nested logical rules. They might come in handy if you need to check user generated rulesets automatically., (*1)

Available rules

"Rules" knows two different rule types. Containers (logical operators/junctions) and rules (logical operands)., (*2)

container rules:, (*3)

  • AND
  • OR
  • XOR
  • NOT

rules:, (*4)

  • True
  • False
  • Compare

For your own usage you will certainly add own rules like "user age >= X" or "basket amount >= Y"., (*5)

Using the rules

Instantiation

You can simply instantiate your rules and nest them like this:, (*6)

$rule = new AndRule(
    new TrueRule(),
    new OrRule(
        new FalseRule(),
        new TrueRule()
    ),
    new NotRule(
        new FalseRule()
    )
);

$rule->validate();

This will return "true" as the logical expression, (*7)

true AND (false OR true) AND NOT false

is true., (*8)

RuleBuilder

In many cases you want to generate your logical tree from an existing data structure. For this you can use the RuleBuilder:, (*9)

$builder = new RuleBuilder(new RuleRegistry());

$result = $builder->fromArray(array(
    'and' => array(
        new TrueRule(),
        new TrueRule()
    ),
    'or' => array(
        'false',
        new TrueRule()
    )
));

Using the fromArray() method of the RuleBuilder you are able to pass your rules as a nested array. The rules can be passed by reference (e.g. new TrueRule()) or by name (e.g. "false"). Any sub-array will result in a new container rule from the type of the array key:, (*10)

array(
    'and' => array()
)

will create a AND container. The above call will result in this rule:, (*11)

(true AND true) AND (false OR true)

The fromArray() method has a second optional parameter "containerType". By default this is AND. So the logical elements on the first level will be linked with AND., (*12)

Own rules

You can create own rules quite easily. For containers you should implement the "container" interface, for simple rules the "rule" interface., (*13)

class UserAgeRule implements Rule
{
    protected $user;
    public function __construct($user)
    {
        $this->user = $user;
    }

    public function validate()
    {
        return $this->user->getAge() >= 21;
    }
}

Use this as follows:, (*14)

$rule = new AndRule(
    new UserAgeRule($currentUser),
    new SomeOtherRule()
)
$rule->validate();

In order to pass current context information to your rule, you should use the constructor of that rule., (*15)

RuleRegistry

If you want your rules to be supported by the RuleBuilder, you should register them to the RuleRegistry:, (*16)

$registry = new RuleRegistry();
$registry->add('age', new UserAgeRule($currentUser));
$registry->add('someOtherRule', new Callback(function() { return new SomeOtherRule(); }));

$builder = new RuleBuilder($registry);
$rule = $builder->fromArray(array(
    'age',
    'someOtherRule'
));
$rule->validate();

There are generally two ways to register your rule: You can register an instance of your object, (*17)

$registry->add('age', new UserAgeRule($currentUser));

or you can register a callable which returns an instance of your rule:, (*18)

$registry->add('someOtherRule', new Callback(function() { return new SomeOtherRule(); }));

Registering a callable has some advantages over registering an actual instance:, (*19)

  • lazy instantiation: your rule will only be created when needed. Especially useful if you need some expensive calculation for your rule
  • context: when used with the RuleBuilder, you will receive the "config" info in the callback function
  • no cloning needed

Rule configuration

Especially if the rules are somehow user generated, you might need some additional configuration. So instead of having a "user is older then 18" rule, you want a "user is older then X" rule. While this is no problem when instantiating the rule objects manually, you might want to have a way, to automatically configure your rule from within the fromArray() method., (*20)

class MinimumAgeRule implements Rule
{
    protected $user;
    protected $minAge;

    public function __construct($user, $minAge)
    {
        $this->user = $user;
    }

    public function validate()
    {
        return $this->user->getAge() >= $this->minAge;
    }
}

Now you are able to configure your rules like this:, (*21)

$registry = new RuleRegistry();
$registry->add('minimumAge', new Callback(function($minAge) use($currentUser) { return new MinimumAgeRule($currentUser, $minAge); } ));
$registry->add('someOtherRule', new SomeOtherRule());

$builder = new RuleBuilder($registry);
$rule = $builder->fromArray(array(
    'minimumAge' => 21,
    'maximumAge' => 44
));
$rule->validate();

In this case, $currentUser is an object we know in our business logic - so we can just USE it in the callable. $minAge - on the other hand - comes from the nested array object, and is only known during the fromArray() method. As it is passed to our callable, its easy to access, (*22)

The Versions

23/02 2015

dev-master

9999999-dev

Nested rules with php

  Sources   Download

MIT

The Requires

  • php >=5.3.2

 

The Development Requires