dnoegel / rules
使用php嵌套规则
Requires
- php: >=5.3.2
Requires (Dev)
- phpunit/phpunit: @stable
This package is auto-updated.
Last update: 2024-09-04 15:25:22 UTC
README
'Rules' 是一个简单的PHP库,允许您检查嵌套逻辑规则。当您需要自动检查用户生成的规则集时,它们可能会很有用。
可用规则
"Rules" 知道两种不同的规则类型。容器(逻辑运算符/连接符)和规则(逻辑运算数)。
容器规则
- AND
- OR
- XOR
- NOT
规则
- 真
- 假
- 比较
为了您自己的使用,您肯定会添加自己的规则,例如 "用户年龄 >= X" 或 "购物车金额 >= Y"。
使用规则
实例化
您可以直接实例化规则并像这样嵌套它们
$rule = new AndRule(
new TrueRule(),
new OrRule(
new FalseRule(),
new TrueRule()
),
new NotRule(
new FalseRule()
)
);
$rule->validate();
这将返回 "true",因为逻辑表达式是真实的。
true AND (false OR true) AND NOT false
。
RuleBuilder
在许多情况下,您希望从现有的数据结构生成您的逻辑树。为此,您可以使用 RuleBuilder
$builder = new RuleBuilder(new RuleRegistry());
$result = $builder->fromArray(array(
'and' => array(
new TrueRule(),
new TrueRule()
),
'or' => array(
'false',
new TrueRule()
)
));
通过 RuleBuilder 的 fromArray() 方法,您可以将规则作为嵌套数组传递。规则可以通过引用(例如 new TrueRule())或名称(例如 "false")传递。任何子数组都将导致创建一个新的容器规则,其类型为数组键的类型
array(
'and' => array()
)
将创建一个 AND 容器。上面的调用将生成以下规则
(true AND true) AND (false OR true)
fromArray() 方法有一个可选的第二个参数 "containerType"。默认情况下,这是 AND。因此,第一层的逻辑元素将通过 AND 相连。
自定义规则
您可以非常容易地创建自己的规则。对于容器,您应该实现 "container" 接口,对于简单规则,实现 "rule" 接口。
class UserAgeRule implements Rule
{
protected $user;
public function __construct($user)
{
$this->user = $user;
}
public function validate()
{
return $this->user->getAge() >= 21;
}
}
用法如下
$rule = new AndRule(
new UserAgeRule($currentUser),
new SomeOtherRule()
)
$rule->validate();
为了将当前上下文信息传递给您的规则,您应该使用该规则构造函数。
RuleRegistry
如果您希望您的规则由 RuleBuilder 支持,您应该将它们注册到 RuleRegistry 中
$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();
通常有两种注册规则的方式:您可以为您的对象注册一个实例
$registry->add('age', new UserAgeRule($currentUser));
或者您可以注册一个可调用的函数,该函数返回您的规则的一个实例
$registry->add('someOtherRule', new Callback(function() { return new SomeOtherRule(); }));
注册可调用函数与注册实际实例相比有一些优点
- 延迟实例化:您的规则仅在需要时创建。如果您需要为您的规则进行一些昂贵的计算,这特别有用。
- 上下文:当与 RuleBuilder 一起使用时,您将在回调函数中接收到 "config" 信息
- 无需克隆
规则配置
特别是如果规则是用户生成的,您可能需要一些额外的配置。因此,而不是有 "用户年龄大于18" 的规则,您想要一个 "用户年龄大于 X" 的规则。虽然手动实例化规则对象时没有问题,但您可能希望有一种方法,可以从 fromArray() 方法自动配置您的规则。
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;
}
}
现在您可以像这样配置您的规则
$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();
在这种情况下,$currentUser 是我们业务逻辑中知道的对象 - 因此我们可以在可调用的函数中 just USE 它。另一方面,$minAge - 来自嵌套数组对象,并且仅在 fromArray() 方法期间已知。由于它传递给我们的可调用的函数,因此可以轻松访问