rezzza/ruler-bundle
Symfony bundle integrating the Ruler rule engine, letting you define and evaluate business rules and contexts via configuration. Useful for stateless, expression-based decision logic in PHP applications.
account.plan == "pro" and account.seats <= 25, PMs can change eligibility criteria as a configuration change rather than waiting on a release train. The product lever is turnaround time on packaging and access decisions, not the engine itself.Consider only under narrow conditions:
Look elsewhere when:
One-liner for executives: We evaluated a small open-source rules engine that expresses policy — who qualifies for a discount, who gets access to a feature, who is auto-approved — as configuration instead of code. The pattern is worth adopting because it decouples business policy from release cycles. The specific package is not: it targets an obsolete Symfony version, has effectively no user base, and would leave us maintaining abandoned code on a decisioning path. Recommendation: treat it as a design reference, fund a short spike to validate the pattern, and make a build-versus-buy call on the results — not a production commitment.
For engineering: Do not install this bundle into a Laravel application; there is no supported path, and forking an end-of-life Symfony bundle to shim it into Laravel's container is strictly worse than a short port. Instead, isolate decision logic behind a single RuleEvaluator interface in our own namespace, with rules supplied as versioned data (PHP arrays or JSON, not framework config trees) so they are diffable and reviewable. Reimplement the evaluation core as a framework-agnostic, PHP 8, framework-free class in roughly 150–300 lines — RuleSet, Rule, Operator, evaluate(array $context): Decision. Bind it Laravel-natively with one service provider, one publishable config file for rule-set registration, and one injectable contract. If we prefer off-the-shelf, take the underlying Ruler library as a standalone dependency and skip the bundle entirely — but verify PHP 8 compatibility first, since the library is as old as the bundle.
Engineer the failure modes deliberately, because in this engine family they are silent by default: a missing or misnamed context key should fail loudly rather than returning a legitimate-looking false; operator type coercion under PHP 8 (string versus numeric comparison, null handling) is the highest-risk class of bug and must be pinned by contract tests; malformed rule sets and unknown operators should fail at load time, not evaluation time. Build provenance instrumentation from day one — rule-set version identifier, input hash, matched rule IDs, latency — or the first "why did this account get this outcome?" incident becomes unbounded.
Sequencing the ask: (1) Spike — encode three real production rules in a standalone evaluator and judge clarity and testability. (2) Benchmark — evaluation latency at realistic rule count and per-request call volume, confirming short-circuit ordering is controllable. (3) Decide — if rules stay engineer-owned, ship the ported evaluator as a first-party package with contract tests and a short rule-authoring guide; if business users need to author or change rules without deploys, stop, because this class of engine is the wrong end state and a hosted decision service or a policy language is the right comparison.
The decision for the group: adopt the capability — externalized, testable business rules behind a clean seam — and reject the dependency. The honest total-cost comparison is not "bundle versus build"; it is "abandoned code we now own" versus "code we wrote and already own." The latter is cheaper by construction. One named internal owner must be assigned to the decision layer, along with an escalation story for contested outcomes, before anything ships.
How can I help you explore Laravel packages today?