Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Rule Bundle Laravel Package

elcodi/rule-bundle

Rule Bundle is part of Elcodi, an e-commerce suite of Symfony components and bundles under MIT license. It provides a flexible rules engine for defining conditions and actions in your store. Note: read-only package; use the main elcodi/elcodi repo for issues, questions, and pull requests.

View on GitHub
Deep Wiki
Context7

Getting Started

Before writing a line of code, understand what you're actually installing. elcodi/rule-bundle is a read-only Symfony bundle — a subtree split of the elcodi/elcodi monorepo. It will not boot under a Laravel kernel: it ships a Symfony Bundle class, DI extensions, compiler passes, and YAML/XML service definitions. composer require elcodi/rule-bundle in a Laravel 10/11 app will very likely fail on Symfony/Doctrine version constraints, and even if it installs, there is no service provider to register it.

So the realistic "getting started" is a spike, not an install:

  1. Clone it to a scratch directory (don't add it to your app's composer.json): git clone https://github.com/elcodi/RuleBundle /tmp/rule-bundle.
  2. Read Resources/config/services.yml first. The bundle is ~90% wiring; the actual behavior lives in the elcodi/rule component (a separate package). Note the service IDs for the rule manager, factory, and repository — those are the seams you'd port.
  3. Read the component's domain model — typically a Rule, RuleGroup, Expression, and Action set of entities/interfaces. This is the part worth keeping. Everything around it is Symfony plumbing you'll discard.
  4. Decide your exit: reimplement (lean — the core is usually a few classes) or extract-and-port (preserve behavior via characterization tests). A one-day spike on the domain model is the right budget.

First use case: model a "10% off carts over $100 for logged-in customers" promotion as data, not code — a named rule, a condition group, and an action. That single scenario tells you whether the package's decomposition is richer than what you'd write yourself in a week (it usually isn't, for a v1).

Implementation Patterns

If you proceed, do it as internal code you own, not as a dependency.

Extraction pattern (recommended). Fork the subtree into packages/rule-engine via a Composer path repository, strip all Symfony DI wiring, and wrap the domain classes in a Laravel service provider:

// app/Providers/RuleEngineServiceProvider.php
public function register(): void
{
    $this->app->bind(RuleRepository::class, EloquentRuleRepository::class);
    $this->app->singleton(RuleEvaluator::class, fn ($app) =>
        new RuleEvaluator($app->make(RuleRepository::class))
    );
}

Preserve the evaluation core verbatim so you can diff behavior against the original while you port.

Persistence pattern. Replace Doctrine repositories with Eloquent. The persisted model is what matters — rules, groups, and their condition/action rows:

  • rules (id, name, enabled, priority)
  • rule_groups (id, rule_id, combinator: all|any)
  • rule_conditions (id, group_id, type, operator, value)
  • rule_actions (id, rule_id, type, payload JSON)

Keep rule definitions data-driven — that is the whole point of the decomposition. Merchandisers edit rows; engineers ship condition/action types.

Evaluation workflow (the loop you'll live in):

  1. Build a context object from your Eloquent models (cart, customer, product) — Elcodi assumes its own e-commerce domain, so map your entities into a plain array/DTO before evaluation. Don't pass Eloquent models into the engine directly.
  2. Load candidate rules, ordered by priority (and cached — see below).
  3. Evaluate each rule's condition groups, resolve to a boolean.
  4. Run the actions of matched rules; collect results.
  5. Return a result set, not a side effect — let the caller apply discounts/shipping.

Integration tip. Keep the engine framework-agnostic inside — plain PHP, no Illuminate or Symfony imports in the evaluation core. Your service provider and Eloquent repository are the only Laravel-aware edges. This makes it testable with plain PHPUnit and portable if you ever swap.

Condition/action registry. Follow the package's extensibility idea: register condition and action types by string key in a registry, resolved from the container. Adding a promotion type becomes "add a class + register a key," not "edit a switch."

Gotchas and Tips

  • You are the maintainer, forever. Read-only upstream + dormant project = no bug fixes, no security patches, no PHP 8.x/Symfony 7 compatibility promises. Budget for periodic audits. If you can't name an internal owner, don't adopt.
  • Expect modernization work. The codebase is PHP 5.x/7.0-era: dynamic properties (PHP 8.2 deprecation), missing return types, old Doctrine APIs. Budget a cleanup pass before production.
  • Composer conflicts are likely, not theoretical. Symfony 2.x/3.x and Doctrine pins will clash with Laravel's Symfony 6/7 stack. This is why extraction (not installation) is the only durable route.
  • Fail-closed vs. fail-open is a policy decision — make it explicit and tested. Malformed expressions throwing in the checkout path is the classic incident. Default to fail-closed on pricing and log every evaluation error with rule ID and a context hash.
  • Watch ordering and precedence. Rule priority, group combinators (all/any), and interaction between overlapping rules are the bug factory. Write tests that assert the final applied result, not just individual condition evaluations.
  • Performance lives in the request path. Cache compiled rules and memoize per-context evaluations. Watch for N+1 rule loading and repeated expression parsing at realistic rule counts (dozens to hundreds). Benchmark before shipping to checkout.
  • No tests in this artifact. There's no test suite to lean on — write characterization tests against the original behavior during extraction so a refactor doesn't silently change semantics.
  • Docs are a stub. No API documentation, no changelog. You'll learn from source. The referenced Gitter/StackOverflow/Twitter channels are stale; treat any issue as an internal ticket.
  • Weigh the alternative first. Symfony ExpressionLanguage (standalone, installable via Composer) plus a thin domain layer covers most of what this bundle does for a v1. Sylius's promotion bundle is the actively maintained equivalent if you want prior art. Reassess Elcodi only if the parent project revives or a maintained Laravel-native engine appears — neither is likely.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect