{"id":20665001,"url":"https://github.com/nicoswd/php-rule-parser","last_synced_at":"2025-04-05T22:06:25.852Z","repository":{"id":35243571,"uuid":"39503126","full_name":"nicoSWD/php-rule-parser","owner":"nicoSWD","description":"PHP Rule Engine - Parses \u0026 Evaluates JavaScript-like expressions","archived":false,"fork":false,"pushed_at":"2022-03-20T22:20:27.000Z","size":764,"stargazers_count":129,"open_issues_count":4,"forks_count":19,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-03-29T21:04:51.761Z","etag":null,"topics":["brms","business-rules","dsl","evaluator","parser","php","php-rule-engine","rule-engine","rule-parser","rule-system","workflow"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nicoSWD.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-07-22T11:46:22.000Z","updated_at":"2025-02-20T14:07:51.000Z","dependencies_parsed_at":"2022-09-16T20:00:25.427Z","dependency_job_id":null,"html_url":"https://github.com/nicoSWD/php-rule-parser","commit_stats":null,"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicoSWD%2Fphp-rule-parser","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicoSWD%2Fphp-rule-parser/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicoSWD%2Fphp-rule-parser/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicoSWD%2Fphp-rule-parser/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nicoSWD","download_url":"https://codeload.github.com/nicoSWD/php-rule-parser/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247406087,"owners_count":20933803,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["brms","business-rules","dsl","evaluator","parser","php","php-rule-engine","rule-engine","rule-parser","rule-system","workflow"],"created_at":"2024-11-16T19:27:22.281Z","updated_at":"2025-04-05T22:06:25.835Z","avatar_url":"https://github.com/nicoSWD.png","language":"PHP","readme":"## PHP Rule Engine\n\n\n[![Latest Stable Version](https://travis-ci.org/nicoSWD/php-rule-parser.svg?branch=master)](https://travis-ci.org/nicoSWD/php-rule-parser)\n[![Build status][Master coverage image]][Master coverage] \n[![Code Quality][Master quality image]][Master quality] \n[![StyleCI](https://styleci.io/repos/39503126/shield?branch=master\u0026style=flat)](https://styleci.io/repos/39503126)\n\n[![Total Downloads](https://img.shields.io/packagist/dt/nicoswd/php-rule-parser.svg)](https://packagist.org/packages/nicoswd/php-rule-parser) \n[![Latest Stable Version](https://img.shields.io/packagist/v/nicoswd/php-rule-parser.svg)](https://packagist.org/packages/nicoswd/php-rule-parser)\n\nYou're looking at a standalone PHP library to parse and evaluate text based rules with a Javascript-like syntax. This project was born out of the necessity to evaluate hundreds of rules that were originally written and evaluated in JavaScript, and now needed to be evaluated on the server-side, using PHP.\n\nThis library has initially been used to change and configure the behavior of certain \"Workflows\" (without changing actual code) in an intranet application, but it may serve a purpose elsewhere.\n\n\nFind me on Twitter: @[nicoSWD](https://twitter.com/nicoSWD)\n\n(If you're using PHP 5, you might want to take a look at [version 0.4.0](https://github.com/nicoSWD/php-rule-parser/tree/0.4.0))\n\n[![SensioLabsInsight](https://insight.sensiolabs.com/projects/67203389-970c-419c-9430-a7f9a005bd94/big.png)](https://insight.sensiolabs.com/projects/67203389-970c-419c-9430-a7f9a005bd94)\n\n## Install\n\nVia Composer\n\n```bash\n$ composer require nicoswd/php-rule-parser\n```\n\n## Bundles\n\nThis library works best with one of these bundles below, but they're not required\n\n| Bundle   | Framework      | Packagist     |\n| -------- |  ------------- | ------------- |\n| [nicoSWD/rule-engine-bundle](https://github.com/nicoSWD/rule-engine-bundle) | Symfony | [![Latest Stable Version](https://img.shields.io/packagist/v/nicoswd/symfony-rule-engine-bundle.svg)](https://packagist.org/packages/nicoswd/symfony-rule-engine-bundle) |\n\n## Usage Examples\n\nTest if a value is in a given array\n```php\n$variables = ['foo' =\u003e 6];\n\n$rule = new Rule('foo in [4, 6, 7]', $variables);\nvar_dump($rule-\u003eisTrue()); // bool(true)\n```\n\nSimple array manipulation \n```php\n$rule = new Rule('[1, 4, 3].join(\".\") === \"1.4.3\"');\nvar_dump($rule-\u003eisTrue()); // bool(true)\n```\n\nTest if a value is between a given range\n```php\n$variables = ['threshold' =\u003e 80];\n\n$rule = new Rule('threshold \u003e= 50 \u0026\u0026 threshold \u003c= 100', $variables);\nvar_dump($rule-\u003eisTrue()); // bool(true)\n```\n\nCall methods on objects from within rules\n```php\nclass User\n{\n    // ...\n\n    public function points(): int\n    {\n        return 1337;    \n    }\n}\n\n$variables = [\n    'user' =\u003e new User(),\n];\n\n$rule = new Rule('user.points() \u003e 300', $variables);\nvar_dump($rule-\u003eisTrue()); // bool(true)\n```\nFor security reasons, PHP's magic methods like `__construct` and `__destruct` cannot be \ncalled from within rules. However, `__call` will be invoked automatically if available,\nunless the called method is defined. \n\n## Built-in Methods\n\nName        | Example             \n----------- | ------------------------\ncharAt      | `\"foo\".charAt(2) === \"o\"`            \nconcat      | `\"foo\".concat(\"bar\", \"baz\") === \"foobarbaz\"`\nendsWith    | `\"foo\".endsWith(\"oo\") === true`               \nstartsWith  | `\"foo\".startsWith(\"fo\") === true`        \nindexOf     | `\"foo\".indexOf(\"oo\") === 1`                \njoin        | `[\"foo\", \"bar\"].join(\",\") === \"foo,bar\"`            \nreplace     | `\"foo\".replace(\"oo\", \"aa\") === \"faa\"`               \nsplit       | `\"foo-bar\".split(\"-\") === [\"foo\", \"bar\"]`           \nsubstr      | `\"foo\".substr(1) === \"oo\"`                 \ntest        | `\"foo\".test(/oo$/) === true`                     \ntoLowerCase | `\"FOO\".toLowerCase() === \"foo\"`                      \ntoUpperCase | `\"foo\".toUpperCase() === \"FOO\"`                      \n\n## Built-in Functions\n\nName        | Example             \n----------- | ------------------------\nparseInt    | `parseInt(\"22aa\") === 22`            \nparseFloat  | `parseFloat(\"3.1\") === 3.1`\n\n## Supported Operators\n\nType        | Description              | Operator\n----------- | ------------------------ | ----------\nComparison  | greater than             | \u003e\nComparison  | greater than or equal to | \u003e=\nComparison  | less than                | \u003c\nComparison  | less or equal to         | \u003c=\nComparison  | equal to                 | ==\nComparison  | not equal to             | !=\nComparison  | identical                | ===\nComparison  | not identical            | !==\nContainment | contains                 | in \nContainment | does not contain         | not in \nLogical     | and                      | \u0026\u0026\nLogical     | or                       | \\|\\|\n\n## Error Handling\n\nBoth, `$rule-\u003eisTrue()` and `$rule-\u003eisFalse()` will throw an exception if the syntax is invalid. These calls can either be placed inside a `try` / `catch` block, or it can be checked prior using `$rule-\u003eisValid()`.\n\n```php\n$ruleStr = '\n    (2 == 2) \u0026\u0026 (\n        1 \u003c 3 \u0026\u0026 3 == 2 ( // Missing and/or before parentheses\n            1 == 1\n        )\n    )';\n\n$rule = new Rule($ruleStr);\n\ntry {\n    $rule-\u003eisTrue();\n} catch (\\Exception $e) {\n    echo $e-\u003egetMessage();\n}\n```\n\nOr alternatively:\n\n```php\nif (!$rule-\u003eisValid()) {\n    echo $rule-\u003egetError();\n}\n```\n\nBoth will output: `Unexpected token \"(\" at position 25 on line 3`\n\n## Syntax Highlighting\n \nA custom syntax highlighter is also provided.\n\n```php\nuse nicoSWD\\Rule;\n\n$ruleStr = '\n    // This is true\n    2 \u003c 3 \u0026\u0026 (\n        // This is false\n        foo in [4, 6, 7] ||\n        // True\n        [1, 4, 3].join(\"\") === \"143\"\n    ) \u0026\u0026 (\n        // True\n        \"foo|bar|baz\".split(\"|\" /* uh oh */) === [\"foo\", /* what */ \"bar\", \"baz\"] \u0026\u0026\n        // True\n        bar \u003e 6\n    )';\n\n$highlighter = new Rule\\Highlighter\\Highlighter(new Rule\\Tokenizer());\n\n// Optional custom styles\n$highlighter-\u003esetStyle(\n    Rule\\Constants::GROUP_VARIABLE,\n    'color: #007694; font-weight: 900;'\n);\n\necho $highlighter-\u003ehighlightString($ruleStr);\n```\n\nOutputs:\n\n![Syntax preview](https://s3.amazonaws.com/f.cl.ly/items/0y1b0s0J2v2v1u3O1F3M/Screen%20Shot%202015-08-05%20at%2012.15.21.png)\n\n## Notes\n\n- Parentheses can be nested, and will be evaluated from right to left.\n- Only value/variable comparison expressions with optional logical ANDs/ORs, are supported.\n\n## Security\n\nIf you discover any security related issues, please email security@nic0.me instead of using the issue tracker.\n\n## Testing\n\n```shell\n$ composer test\n```\n\n## Contributing\n\nPull requests are very welcome! If they include tests, even better. This project follows PSR-2 coding standards, please make sure your pull requests do too.\n\n## To Do\n\n- Support for object properties (foo.length)\n- Support for returning actual results, other than true or false\n- Support for array / string dereferencing: \"foo\"[1]\n- Don't force boolean comparison for tokens that are already booleans. `my_func() \u0026\u0026 2 \u003e 1` should work\n- Change regex and implementation for method calls. \".split(\" should not be the token\n- Add / implement missing methods\n- Add \"typeof\" construct\n- Do math (?)\n- Allow string concatenating with \"+\"\n- Invalid regex modifiers should not result in an unknown token\n- Duplicate regex modifiers should throw an error\n- ~~Add support for function calls~~\n- ~~Support for regular expressions~~\n- ~~Fix build on PHP 7 / Nightly~~\n- ~~Allow variables in arrays~~\n- ~~Verify function and method name spelling (.tOuPpErCAse() is currently valid)~~\n- ...\n\n## License\n\n[![License](https://img.shields.io/packagist/l/nicoSWD/php-rule-parser.svg)](https://packagist.org/packages/nicoswd/php-rule-parser)\n\n  [Master]: https://github.com/nicoSWD/php-rule-parser/tree/master\n  [Master coverage image]: https://scrutinizer-ci.com/g/nicoSWD/php-rule-parser/badges/coverage.png?b=master\n  [Master coverage]: https://scrutinizer-ci.com/g/nicoSWD/php-rule-parser/?branch=master\n  [Master quality image]: https://img.shields.io/scrutinizer/g/nicoswd/php-rule-parser.svg?b=master\n  [Master quality]: https://scrutinizer-ci.com/g/nicoSWD/php-rule-parser/?branch=master\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnicoswd%2Fphp-rule-parser","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnicoswd%2Fphp-rule-parser","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnicoswd%2Fphp-rule-parser/lists"}