PHPackages                             superruzafa/rules - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. superruzafa/rules

ActiveLibrary

superruzafa/rules
=================

A rule engine following the condition -&gt; action paradigm

1.0.1(11y ago)1672MITPHPPHP &gt;=5.3

Since Nov 17Pushed 11y ago1 watchersCompare

[ Source](https://github.com/superruzafa/rules)[ Packagist](https://packagist.org/packages/superruzafa/rules)[ RSS](/packages/superruzafa-rules/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (2)Versions (3)Used By (0)

Rules
=====

[](#rules)

[![Build Status](https://camo.githubusercontent.com/d4962d161387553bb5f5e4dc91dbcc94d71fd62fb127e4e0f3021d5e39e3af77/68747470733a2f2f7472617669732d63692e6f72672f737570657272757a6166612f72756c65732e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/superruzafa/rules)

A rule engine following the condition -&gt; action paradigm

What a rule is?
---------------

[](#what-a-rule-is)

A rule is build up by three elements:

#### One condition

[](#one-condition)

Every rule has a boolean condition. If the condition is satisfied (i.e, its value is not false) then the rule is processed.

#### Some actions

[](#some-actions)

Every rule has some associated actions. The actions could be performed at different rule's stages:

- Before the rule's condition being evaluated (regardless being satisfied or not)
- After its condition has been satisfied but before its subrules have been executed
- After both its condition has been satisfied and its subrules have been executed.
- Before *leave* the rule's, regardless the condition has been satisfied or not.

#### Zero or more subrules

[](#zero-or-more-subrules)

Each rule could contain subrules. Each subrule is executed only if the parent rule's condition has been satisfied.

When executes, the flow a rule follows could be described as:

```
Perform pre-rule actions
If the rule's condition is satisfied then
    Perform pre-subrules actions
    Execute subrules
    Perform post-subrules actions
Perform post-rule actions

```

Quick example
=============

[](#quick-example)

```
$ctx = new Context();
$ctx['name'] = 'Philip J.';
$ctx['surname'] = 'Fry';

// If the context's name is 'Philip J.' AND the context's surname is 'Fry'...
$condition = new AndOp(
    new EqualTo('{{ name }}', 'Philip J.'),
    new EqualTo('{{ surname }}', 'Fry')
);

// Then print the message
$action = new RunCallback(function (Context $c) {
    echo 'Hello, my name is ' . $c['name'] . $c['surname'];
});

$rule = new Rule();
$rule
    ->setCondition($condition)
    ->setAction($action)
    ->execute($ctx);

// Hello, my name is Philip J. Fry
```

Conditions
==========

[](#conditions)

Conditions use boolean expressions to check whether the rule must be processed. By default, a rule has a `true` as a condition.

### Primitives

[](#primitives)

There are four predefined primitives:

- String
- Integer
- Float
- Boolean

### Operators

[](#operators)

Operators take one, two or more values (primitives or other operator's output) and return some other value

### Logical operators

[](#logical-operators)

#### `AndOp($expr [, $expr]*)`

[](#andopexpr--expr)

`AndOp()` operator takes one or more arguments and returns `true` if *all* of its arguments are evaluated as `true`:

```
$and = new AndOp(true, false, false, true);
echo $and->evaluate(); // evaluate(); // evaluate(); // evaluate(); // evaluate(); // perform($ctx);

var_dump($ctx);
// array(
//     'name' => 'Philip J.',
//     'surname' => 'Fry'
// );
```

### Interpolate context

[](#interpolate-context)

This action allows to render the current context as a template by feeding itself as the variable replacements:

```
$ctx = new Context();
$ctx['name'] = 'Philip J.';
$ctx['surname'] = 'Fry';
$ctx['fullname'] = '{{ name }} {{ surname }}';

$action = new InterpolateContext();
$action->perform($ctx);

var_dump($ctx);
// array(
//     'name' => 'Philip J.',
//     'surname' => 'Fry'
//     'fullname' => 'Philip J. Fry'
// );
```

### Filter context

[](#filter-context)

This action filter (either by preserving or discarding) entries in a context:

```
$ctx = new Context();
$ctx['name'] = 'Philip J.';
$ctx['surname'] = 'Fry';
$ctx['fullname'] = 'Philip J. Fry';

$action = new FilterContext();
$action
    ->setKeys('fullname')
    ->setMode(FilterContext::ALLOW_KEYS)
    ->perform($ctx);

var_dump($ctx);
// array(
//     'fullname' => 'Philip J. Fry'
// );
```

### Run callback

[](#run-callback)

This actions calls a custom user function passing the current context as argument:

```
$ctx = new Context();
$ctx['name'] = 'Philip J.';
$ctx['surname'] = 'Fry';

$callback = function(Context $ctx) {
    $ctx['fullname'] = $ctx['name'] . ' ' . $ctx['surname'];
    unset($ctx['surname'];
}

$action = new RunCallback($callback);
$action->perform($ctx);

var_dump($ctx);
// array(
//     'name' => 'Philip J.',
//     'fullname' => 'Philip J. Fry'
// );
```

### No action

[](#no-action)

This actions does nothing :)

```
$ctx = new Context();
$ctx['name'] = 'Philip J.';
$ctx['surname'] = 'Fry';

$action = new NoAction($callback);
$action->perform($ctx);

var_dump($ctx);
// array(
//     'name' => 'Philip J.',
//     'surname' => 'Fry'
// );
```

### Sequence

[](#sequence)

This actions allows to define a list of actions to be performed sequentially:

```
$ctx = new Context();
$ctx['fullname'] = '{{ name }} {{ surname }}';

$override = new OverrideContext(new Context(array('name' => 'Philip J.')));     // Adds name
$callback = new RunCallback(function (Context $c) { $c['surname'] = 'Fry'; } ); // Adds surname
$interpolate = new InterpolateContext();                                        // Interpolates fullname
$filter = new FilterContext(FilterContext::ALLOW_KEYS, 'fullname');             // Filters all except fullname

$sequence = new Sequence($override, $callback);
$sequence->appendAction($interpolate)->appendAction($filter);
$sequence->perform($ctx);

var_dump($ctx);
// array(
//     'fullname' => 'Philip J. Fry'
// );
```

###  Health Score

28

—

LowBetter than 54% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity12

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity59

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~105 days

Total

2

Last Release

4094d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/c0683d4538ea829259ad3efe9dba794c5f93465433e320a61a6a2998a8839687?d=identicon)[superruzafa](/maintainers/superruzafa)

---

Top Contributors

[![superruzafa](https://avatars.githubusercontent.com/u/231822?v=4)](https://github.com/superruzafa "superruzafa (20 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/superruzafa-rules/health.svg)

```
[![Health](https://phpackages.com/badges/superruzafa-rules/health.svg)](https://phpackages.com/packages/superruzafa-rules)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
