GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — GitHub - nicoSWD/php-rule-parser: PHP Rule Engine - Parses & Evaluates JavaScript-like expressions

BranchesTags
Open more actions menu

Latest commit

 

History

297 Commits
297 Commits

Folders and files

NameName
Last commit message
Last commit date
.github/workflows
.github/workflows
 
 
src
src
 
 
tests
tests
 
 
.editorconfig
.editorconfig
 
 
.gitattributes
.gitattributes
 
 
.gitignore
.gitignore
 
 
.php-cs-fixer.dist.php
.php-cs-fixer.dist.php
 
 
.styleci.yml
.styleci.yml
 
 
LICENSE.md
LICENSE.md
 
 
README.md
README.md
 
 
composer.json
composer.json
 
 
depfile.yaml
depfile.yaml
 
 
phpstan.neon
phpstan.neon
 
 
phpunit.xml.dist
phpunit.xml.dist
 
 

Repository files navigation

PHP Rule Engine

Latest Stable Version Total Downloads Code Quality StyleCI Code Coverage

A PHP library that parses and evaluates boolean expressions using a JavaScript-like syntax. It supports variables, comparison and logical operators, arithmetic, regular expressions, arrays, string methods, and function calls, all from plain text rules.

Install

Via Composer

composer install nicoswd/php-rule-parser

Usage Examples

E-commerce: Validate coupon eligibility

$variables = [
    'cart_total'     => 120,
    'user_tier'      => 'gold',
    'is_blacklisted' => false,
];

$rule = new Rule('
    cart_total >= 50 && 
    user_tier in ["gold", "platinum"] &&
    !is_blacklisted
', $variables);

var_dump($rule->isTrue()); // bool(true) — eligible for discount

Access control: Check user permissions

$variables = [
    'role'         => 'editor',
    'is_suspended' => false,
];

$rule = new Rule('role in ["admin", "editor"] && !is_suspended', $variables);
var_dump($rule->isTrue()); // bool(true) — access granted

Pricing: Calculate order total with conditions

$variables = [
    'base_price' => 29.99,
    'tax_rate'   => 21,
    'quantity'   => 3,
];

$rule = new Rule('(base_price + (base_price * tax_rate / 100)) * quantity', $variables);
var_dump($rule->result()); // float(108.8571...) — total with tax

Form validation: Check input constraints

$variables = [
    'age'     => 25,
    'country' => 'US',
];

$rule = new Rule('age >= 18 && country in ["US", "CA", "UK"]', $variables);
var_dump($rule->isTrue()); // bool(true) — valid registration

Notification routing: Target specific users

$variables = [
    'plan'                 => 'pro',
    'last_login'           => 3,
    'notification_opt_out' => false,
];

$rule = new Rule('
    plan in ["pro", "enterprise"] &&
    last_login < 7 &&
    !notification_opt_out
', $variables);

var_dump($rule->isTrue()); // bool(true) — send notification

Feature flags: Roll out features gradually

$variables = [
    'user_id' => 7,
];

$rule = new Rule('user_id % 10 < 3', $variables);
var_dump($rule->isTrue()); // bool(true) — feature enabled for this user

String manipulation: Format user data

$variables = [
    'firstName' => 'John',
    'lastName'  => 'Doe',
];

$rule = new Rule('firstName.toUpperCase() + " " + lastName.toUpperCase()', $variables);
var_dump($rule->result()); // string("JOHN DOE")

Object method calls: Evaluate complex conditions

class Subscription
{
    public function isActive(): bool
    {
        return true;
    }

    public function daysUntilExpiry(): int
    {
        return 15;
    }
}

$variables = [
    'subscription' => new Subscription(),
];

$rule = new Rule('subscription.isActive() && subscription.daysUntilExpiry() > 7', $variables);
var_dump($rule->isTrue()); // bool(true) — subscription is active and not expiring soon

Arithmetic: Operator precedence

$rule = new Rule('2 + 3 * 4 == 14');
var_dump($rule->isTrue()); // bool(true) - multiplication before addition

$rule = new Rule('(2 + 3) * 4 == 20');
var_dump($rule->isTrue()); // bool(true) - parentheses override precedence

Arithmetic: Unary operators

$rule = new Rule('-5 * 3 == -15');
var_dump($rule->isTrue()); // bool(true) - unary minus

$rule = new Rule('!false');
var_dump($rule->isTrue()); // bool(true) - logical NOT

$rule = new Rule('!(1 == 2)');
var_dump($rule->isTrue()); // bool(true) - NOT with comparison

Note

For security reasons, PHP's magic methods like __construct and __destruct cannot be called from within rules. However, __call will be invoked automatically if available, unless the called method is defined.

Built-in Methods

Name Example
charAt "foo".charAt(2) === "o"
concat "foo".concat("bar", "baz") === "foobarbaz"
endsWith "foo".endsWith("oo")
startsWith "foo".startsWith("fo")
indexOf "foo".indexOf("oo") === 1
join ["foo", "bar"].join(",") === "foo,bar"
replace "foo".replace("oo", "aa") === "faa"
split "foo-bar".split("-") === ["foo", "bar"]
substr "foo".substr(1) === "oo"
test "foo".test(/oo$/)
toLowerCase "FOO".toLowerCase() === "foo"
toUpperCase "foo".toUpperCase() === "FOO"

Built-in Functions

Name Example
parseInt parseInt("22aa") === 22
parseFloat parseFloat("3.1") === 3.1

Supported Operators

Type Description Operator
Comparison greater than >
Comparison greater than or equal to >=
Comparison less than <
Comparison less or equal to <=
Comparison equal to ==
Comparison not equal to !=
Comparison identical ===
Comparison not identical !==
Containment contains in
Containment does not contain not in
Logical and &&
Logical or ||
Arithmetic addition +
Arithmetic subtraction -
Arithmetic multiplication *
Arithmetic division /
Arithmetic modulo %
Unary negation -
Unary logical NOT !

Error Handling

Both $rule->isTrue() and $rule->isFalse() will throw an exception if the syntax is invalid. These calls can either be placed inside a try / catch block, or validity can be checked beforehand using $rule->isValid().

$ruleStr = '
    (2 == 2) && (
        1 < 3 && 3 == 2 ( // Missing and/or before parentheses
            1 == 1
        )
    )';

$rule = new Rule($ruleStr);

try {
    $rule->isTrue();
} catch (\Exception $e) {
    echo $e->getMessage();
}

Or alternatively:

if (!$rule->isValid()) {
    echo $rule->error;
}

Both will output: Unexpected "(" at position 28

Syntax Highlighting

A custom syntax highlighter is also provided.

use nicoSWD\Rule\Highlighter\Highlighter;
use nicoSWD\Rule\TokenStream\Token\TokenType;

$ruleStr = '
    // This is true
    2 < 3 && (
        // This is false
        foo in [4, 6, 7] ||
        // True
        [1, 4, 3].join("") === "143"
    ) && (
        // True
        "foo|bar|baz".split("|" /* uh oh */) === ["foo", /* what */ "bar", "baz"] &&
        // True
        bar > 6
    )';

$highlighter = new Highlighter();

// Optional custom styles
$highlighter->setStyle(
    TokenType::VARIABLE,
    'color: #007694; font-weight: 900;'
);

echo $highlighter->highlightString($ruleStr);

Outputs:

Syntax preview

Security

If you discover any security related issues, please email [email protected] instead of using the issue tracker.

Testing

$ composer test

Contributing

Pull requests are very welcome! If they include tests, even better. This project follows PSR-12 coding standards, please make sure your pull requests do too.

To Do

  • Support for object properties (foo.length)
  • Support for array / string dereferencing: "foo"[1]
  • Support for returning actual results, other than true or false
  • Don't force boolean comparison for tokens that are already booleans. my_func() && 2 > 1 should work
  • Allow string concatenating with "+"
  • Duplicate regex modifiers should throw an error
  • Add support for function calls
  • Support for regular expressions
  • Fix build on PHP 7 / Nightly
  • Allow variables in arrays
  • Verify function and method name spelling (.tOuPpErCAse() is currently valid)
  • Change regex and implementation for method calls
  • Add / implement missing methods
  • Invalid regex modifiers should not result in an unknown token
  • ...

License

License

About

PHP Rule Engine - Parses & Evaluates JavaScript-like expressions

Topics

brmsbusiness-rulesdslevaluatorparserphpphp-rule-enginerule-enginerule-parserrule-systemworkflow

Resources

Readme
MIT license
Activity

Stars

130 stars

Watchers

6 watching

Forks

18 forks
Report repository

Releases

Used by

Contributors

Languages

You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.