PHPackages                             jakubciszak/rule-engine - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. jakubciszak/rule-engine

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

jakubciszak/rule-engine
=======================

1.3.0(7mo ago)362MITPHPPHP ^8.4CI passing

Since Oct 9Pushed 6mo ago1 watchersCompare

[ Source](https://github.com/jakubciszak/rule-engine)[ Packagist](https://packagist.org/packages/jakubciszak/rule-engine)[ RSS](/packages/jakubciszak-rule-engine/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (9)Dependencies (2)Versions (36)Used By (0)

Rule Engine
===========

[](#rule-engine)

Rule Engine lets you express business logic in plain PHP arrays and evaluate it with ease. Pick the API that matches the shape of your data:

- **FlatRuleAPI** – send a linear array in [Reverse Polish Notation](https://en.wikipedia.org/wiki/Reverse_Polish_notation) for fast stack-based evaluation.
- **NestedRuleApi** – describe rules as nested associative arrays that read like infix notation.
- **StringRuleApi** – parse and evaluate human readable infix expressions.

Both APIs accept arrays decoded from JSON and can work with callables inside the evaluation context, giving you a flexible way to run rules or trigger simple actions.

How it works
------------

[](#how-it-works)

The library implements the **Rule Archetype Pattern** from the book ["Enterprise Patterns and MDA: Building Better Software with Archetype Patterns and UML"](https://amzn.eu/d/arcbwKu) by Jim Arlow and Ila Neustadt. Rules are composed of propositions, operators and optional actions. Depending on whether you use `FlatRuleAPI` or `NestedRuleApi`, the rule is converted to a uniform internal structure that the engine evaluates against the provided context.

Requirements
------------

[](#requirements)

- PHP 8.4 or higher
- Composer

Installation
------------

[](#installation)

To install the library, use Composer:

```
composer require jakubciszak/rule-engine
```

Usage
-----

[](#usage)

### FlatRuleAPI

[](#flatruleapi)

Rules can also be defined using JSON in RPN order. The example below presents two rules:

```
{
  "rules": [
    {
      "name": "rule1",
      "elements": [
        {"type": "variable", "name": "a"},
        {"type": "variable", "name": "b"},
        {"type": "operator", "name": "=="}
      ]
    },
    {
      "name": "rule2",
      "elements": [
        {"type": "variable", "name": "amount"},
        {"type": "variable", "name": "max"},
        {"type": "operator", "name": ">"}
      ]
    }
  ]
}
```

This JSON can be decoded and passed to the `FlatRuleAPI` context to get the evaluation result as a boolean. The context array is passed by reference and updated with any values changed during evaluation.

```
$rules = json_decode('{"rules": [...]}', true, 512, JSON_THROW_ON_ERROR);
$context = json_decode('{"a":1,"b":2}', true, 512, JSON_THROW_ON_ERROR);
$result = FlatRuleAPI::evaluate($rules, $context);
// $context now contains any modifications made by rule actions
```

### NestedRuleApi

[](#nestedruleapi)

`NestedRuleApi` accepts rules defined using a JSON structure that resembles infix notation. Operators are written as keys and their arguments are provided in nested arrays.

```
use JakubCiszak\RuleEngine\Api\NestedRuleApi;

$rules = ['and' => [
    ['' => [['var' => 'b'], 2]],
];

$data = ['a' => 1, 'b' => 3];

NestedRuleApi::evaluate($ruleset, $data); // true
```

### StringRuleApi usage

[](#stringruleapi-usage)

`StringRuleApi` accepts conditions written as human readable infix expressions. Variables are denoted by a leading dot and resolved from the supplied data array.

```
use JakubCiszak\RuleEngine\Api\StringRuleApi;

$expr = '(.actualAge > 18 or .name is Adam) or (.citizenship is PL and .actualAge > 15)';
$data = ['actualAge' => 16, 'name' => 'John', 'citizenship' => 'PL'];

$result = StringRuleApi::evaluate($expr, $data); // true
```

Complex nested conditions are also supported:

```
$complex = '((.a > 1 and (.b < 3 or .c is 2)) or ((.d >= 5 and .e  18',
    'plCitizen' => '.citizenship is PL',
];
$data = ['actualAge' => 16, 'citizenship' => 'PL'];

$result = StringRuleApi::evaluate($rules, $data); // false
```

Boolean variables can be referenced directly without explicit comparison and negated using `not`:

```
$flags = '.g and not .h';
$data = ['g' => true, 'h' => false];

StringRuleApi::evaluate($flags, $data); // true
```

### Rule actions

[](#rule-actions)

Each rule may include simple actions executed when the rule is evaluated. Actions are expressed as strings:

```
".count + 5"
".name = John"
".total + .amount"

```

Supported operators are `+` (addition), `-` (subtraction), `.` (concatenation) and `=` (assignment). Values starting with `.` reference variables from the evaluation context.

When using `NestedRuleApi`, specify actions under the `actions` key alongside the rule expression or within each rule of a ruleset.

#### FlatRuleAPI example

[](#flatruleapi-example)

```
{
  "rules": [
    {
      "name": "rule1",
      "elements": [
        {"type": "variable", "name": "a"},
        {"type": "variable", "name": "b"},
        {"type": "operator", "name": "=="}
      ],
       "actions": [".count + 1"]
    }
  ]
}
```

Evaluating the JSON above with `{ "a": 1, "b": 1, "count": 0 }` updates `count` to `1` when the rule evaluates to `true`.

```
$rules = json_decode($json, true, 512, JSON_THROW_ON_ERROR); // $json contains JSON above
$context = ['a' => 1, 'b' => 1, 'count' => 0];
FlatRuleAPI::evaluate($rules, $context);
// $context['count'] === 1
```

#### NestedRuleApi example

[](#nestedruleapi-example)

```
$ruleset = [
    'rule1' => [
        '==' => [['var' => 'a'], 1],
        'actions' => ['.count + 1'],
    ],
    'rule2' => [
        '==' => [['var' => 'count'], 1],
    ],
];

$data = ['a' => 1, 'count' => 0];

NestedRuleApi::evaluate($ruleset, $data); // true
// $data['count'] === 1
```

What is behind?
---------------

[](#what-is-behind)

### Pure PHP library usage gives most flexible and powerful solutions

[](#pure-php-library-usage-gives-most-flexible-and-powerful-solutions)

### Notation

[](#notation)

This implementation use [Reverse Polish Notation (RPN)](https://en.wikipedia.org/wiki/Reverse_Polish_notation).
**RPN** is a mathematical notation in which operators follow their operands. This notation eliminates the need for parentheses that are used in standard infix notation, making the evaluation of expressions simpler and more efficient.

For example, the expression
`(2 + 3) * 5`
in standard notation would be written as
`2 3 + 5 *` in RPN.

In this notation, you first add 2 and 3 to get 5, and then multiply by 5 to get 25.

The Rule Engine uses RPN to simplify the process of building conditions, making it more intuitive to construct complex logical expressions.

### Creating Rules

[](#creating-rules)

You can create rules using the provided methods for different operators:

```
use JakubCiszak\RuleEngine\Rule;
use JakubCiszak\RuleEngine\Operator;

$rule = (new Rule())
    ->variable('expectedAge', 22)
    ->variable('age')
    ->greaterThan()
    ->evaluate($context);
```

### Evaluating Rules

[](#evaluating-rules)

To evaluate a rule, you need to provide a `RuleContext`:

```
use JakubCiszak\RuleEngine\RuleContext;

$context = new RuleContext();
$result = $rule->evaluate($context);
```

---

Development
-----------

[](#development)

### Running Tests

[](#running-tests)

To run the tests, use PHPUnit:

```
vendor/bin/phpunit
```

Contributing
------------

[](#contributing)

Contributions are welcome! Please open an issue or submit a pull request.

License
-------

[](#license)

This project is licensed under the MIT License.

Authors
-------

[](#authors)

- Jakub Ciszak -

Additional Information
----------------------

[](#additional-information)

- The project uses native PHP arrays for optimal performance and simplicity.
- The source code is located in the `src/` directory.
- Tests are located in the `tests/` directory.

###  Health Score

42

—

FairBetter than 90% of packages

Maintenance65

Regular maintenance activity

Popularity13

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity68

Established project with proven stability

 Bus Factor1

Top contributor holds 75% 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 ~43 days

Recently: every ~13 days

Total

9

Last Release

230d ago

Major Versions

0.1.1 → 1.0.02025-07-31

PHP version history (2 changes)0.1.0PHP ^8.3

1.0.0PHP ^8.4

### Community

Maintainers

![](https://www.gravatar.com/avatar/235452bbfa7fbe11c5572ac2bd34bca151d3597d81cdb8740c94e74b6b9c7d68?d=identicon)[itdomino](/maintainers/itdomino)

---

Top Contributors

[![jakubciszak](https://avatars.githubusercontent.com/u/30110635?v=4)](https://github.com/jakubciszak "jakubciszak (72 commits)")[![Copilot](https://avatars.githubusercontent.com/in/1143301?v=4)](https://github.com/Copilot "Copilot (24 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/jakubciszak-rule-engine/health.svg)

```
[![Health](https://phpackages.com/badges/jakubciszak-rule-engine/health.svg)](https://phpackages.com/packages/jakubciszak-rule-engine)
```

###  Alternatives

[naffiq/telegram-channel-php

Post to your telegram channel with ease!

124.2k](/packages/naffiq-telegram-channel-php)

PHPackages © 2026

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