kphoen/rulerz-bundle
Symfony bundle that integrates the RulerZ rule engine, providing configuration and services for defining, compiling, and applying business rules to objects and collections. It simplifies dependency injection and rule management in Symfony applications.
This is a Symfony bundle, not a Laravel package — there is no service provider, no facade, and K-Phoen/RulerZBundle was last released in June 2016. A Laravel developer should treat it as documentation for how to wire up the underlying engine (rulerz/rulerz) in a Laravel container, not as something to composer require in a Laravel app. First, read the bundle's DependencyInjection/Configuration.php and Resources/config/services.yml in the repo — they show exactly which pieces you need to replicate: the RulerZ\RulerZ engine, a Compiler, one or more targets, and a cache adapter for compiled rules.
Minimal adaptation in a Laravel service provider:
// composer require rulerz/rulerz
$this->app->singleton(\RulerZ\RulerZ::class, function ($app) {
$evaluator = new \RulerZ\Compiler\EvalEvaluator(); // writes to storage/framework/cache/rulerz
$compiler = new \RulerZ\Compiler\Compiler($evaluator);
return new \RulerZ\RulerZ($compiler, [
new \RulerZ\Target\Native\Native(),
]);
});
First use case: a rule-driven eligibility check where the rule string lives in the database, not the codebase.
$rulerz->satisfies($user, 'points > :min and country in :allowed', [
'min' => 100, 'allowed' => ['FR', 'BE'],
]); // bool
Store rules as data, bind parameters at runtime. This is the core idea the bundle's YAML rulerz.rules config encodes; in Laravel put it in a table (name, rule, parameters json) and never string-interpolate user values into the rule.
$rulerz->filter($users, 'gender = "F" and points > :p', ['p' => 30]); // array
$rulerz->satisfies($user, $rule->rule, $rule->parameters); // bool
$rulerz->apply($query, $rule->rule, $rule->parameters); // compiled target
Gate / policy integration. This replaces the bundle's Symfony voter. Keep it thin so the engine stays swappable:
Gate::define('view-report', function ($user) use ($rulerz, $rule) {
return $rulerz->satisfies($user, $rule->rule, $rule->parameters);
});
Cache compiled rules. Compilation is the expensive part. The bundle wires a rulerz.cache service; in Laravel give the FileEvaluator a directory under storage/framework/cache/rulerz and make sure it is git-ignored and writable.
Validate on write, not on read. When an admin saves a rule, parse/compile it immediately and reject it with a clear error rather than exploding at request time:
try {
$rulerz->compile('points > :p', ['p' => 1]);
} catch (\RulerZ\Exception\RuleCompilationException $e) { /* validation error */ }
Test rules as table-driven fixtures. Because rules are strings, satisfies() against plain arrays is a fast, dependency-free unit test — no database required.
Symfony\Component\HttpKernel\Bundle\Bundle and depends on symfony/config / DI compiler passes. Use rulerz/rulerz directly.composer.json will likely block PHP 8.x. Pin a compatible version, or budget time to fork/vendor it. With 0 dependents and no releases since 2016, assume no upstream fixes.evals them. Rules sourced from user input are a code-execution surface. Restrict who can author rules, whitelist the allowed operator/field set, and validate before persisting.=, !=, <, <=, >, >=, in, not in, and, or, like, with parentheses. No functions, no IS NULL, no arithmetic. Model NULL checks by transforming data before evaluation.filter() is O(n). It materialises and iterates the whole collection. Never use it for paginated listings — for those, translate rules to query-builder scopes or add a custom RulerZ\Target\Target implementation; that interface is the main extension point the bundle exposes as tagged services.EvalEvaluator for FileEvaluator pointed at a scratch directory and read the generated PHP to see exactly how your rule was translated. Most “why doesn't this match” bugs are type coercion ("30" vs 30) or a mistyped field name.RuleEngine interface (satisfies/filter) in your app. Given the package's staleness, you want a one-file swap to something like Symfony ExpressionLanguage or a hand-rolled evaluator later.How can I help you explore Laravel packages today?