radish/radish-bundle
RadishBundle provides Symfony integration for Radish, including bundle configuration, service container wiring, and framework hooks so you can install and use Radish in Symfony applications with minimal setup and no custom bootstrap code.
This is a Symfony bundle, not a Laravel package. The bundle layer (RadishBundle) only registers DI services and config; the actual rule engine lives in radish/radish. For a Laravel codebase you should not install radish/radish-bundle — pull radish/radish directly and wrap it yourself (see Gotchas).
If you are on Symfony (2.x/3.x era), minimal steps:
composer require radish/radish-bundleRadishBundle\RadishBundle in AppKernel::registerBundles()radish: block to app/config/config.yml and point it at a rules file (YAML/PHP) — the extension is in RadishBundle/DependencyInjection/RadishExtension.phpWhere to look first, in order:
Radish\Rule\RuleSet and Radish\Rule\RuleSetBuilder in the core package — this is where rules are assembledRadish\Engine\* — the evaluation loop (forward chaining; rules can trigger other rules)RadishBundle/Resources/config/services.yml — the actual service IDs and class wiring, which is the only real documentation this bundle hasFirst use case: given a fact array like ['customer' => ['age' => 17, 'country' => 'US']], load a ruleset that expresses "deny if age < 18 and country is not FR", and read back the resulting flag / action output. Rules are data; keep them out of PHP classes so non-devs can iterate.
Rules as configuration, engine as a service. The bundle's whole value is that rule definitions live in config files loaded at container compile time, and the RuleSet/engine is a shared service. Treat it as a black-box evaluator: build facts, hand to engine, inspect result.
Fact-shaped DTOs. Radish evaluates against arrays and dot-path expressions. Normalise your Eloquent models into plain arrays with stable keys before calling the engine. Do not pass models directly — nested accessors (order->customer->tier) will not resolve the way rule expressions expect.
Rule authoring loop. Keep a rules/ directory, version it in git, and add a console command / artisan command that evaluates a fixture fact against the current ruleset. Every rule change should be smoke-tested against 3–5 fixture facts in CI. With a 2017 package and no upstream activity, you are the test suite.
Isolating the engine behind an interface. Define your own RuleEvaluator contract in the app, with a Radish-backed implementation. This is the single most important pattern: it lets you swap in a maintained engine (Ruler, Hoa\Ruler, or hand-rolled) without touching call sites, which you will very likely want to do.
Action handling. Rules typically name actions rather than executing code. Use action names as tokens, resolve them in your own dispatcher (match ($actionName) { ... }), and keep side effects in your application, not in rule definitions.
Layered rulesets. Compose small rulesets (eligibility, pricing, fraud) and evaluate them in sequence with the output of one feeding facts into the next. This is more debuggable than one 200-line ruleset and lets you cache/reload independently.
each(), loose assert()-style assumptions, no return types). Test on your target PHP before committing.composer require radish/radish, bind RuleSet/engine as singletons in a service provider, load rules from config/ or a rules/ directory, and skip the bundle entirely. The bundle contributes almost nothing you can't rebuild in ~40 lines.== semantics match PHP's loose comparison, and don't assume null/missing-key handling. Write a test per operator you use (and, or, not, comparisons, membership) before building on it.config:cache will bake them in — load rules lazily from disk instead.(ruleset, fact, matchedRules, result) and dump it on failure. This decorator is also your easiest path off the package later.How can I help you explore Laravel packages today?