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

Rules Bundle Laravel Package

vouchedfor/rules-bundle

vouchedfor/rules-bundle is a PHP package for defining, organizing, and evaluating business rules in a reusable structure. It helps keep rule logic clean and makes rule-based decisions easier to integrate into Laravel or PHP applications.

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check before you install anything. vouchedfor/rules-bundle is a Symfony bundle, not a Laravel package. With 2 stars, 0 dependents and a low score, treat it as unmaintained third-party code: read src/ end to end before you composer require it into a production app. If your stack is Laravel, this will not auto-register, will not boot without symfony/framework-bundle and symfony/dependency-injection, and you will be fighting the container rather than writing rules. Realistically your options are (a) port the rule classes into a plain-PHP/Laravel service provider, or (b) use symfony/expression-language directly, which is almost certainly the actual value here.

If you are on Symfony:

composer require vouchedfor/rules-bundle

Register it manually (old bundles don't ship Symfony Flex recipes):

// config/bundles.php
return [
    // ...
    VouchedFor\RulesBundle\VouchedForRulesBundle::class => ['all' => true],
];

Then look at, in this order:

  1. README.md — often the only documentation; skim for the service ID and rule definition example.
  2. src/DependencyInjection/ — the extension alias tells you the config key (vouched_for_rules, rules, etc.) and any parameters you can override.
  3. src/Resources/config/services.* — reveals the public service IDs and which interface you must implement.
  4. tests/ — usually the real documentation. Copy a test fixture as your first rule.

First use case: write one rule that answers a yes/no business question about a domain object ("can this order be refunded?", "is this review eligible for publication?") and evaluate it from a console command before wiring it into a controller. Keep the first integration read-only and side-effect free.

Implementation Patterns

Rules as tagged services. The standard Symfony shape for this kind of bundle is an interface plus a DI tag. Expect something like:

final class ReviewIsPublishable implements RuleInterface
{
    public function supports(object $subject): bool
    {
        return $subject instanceof Review;
    }

    public function evaluate(object $subject): bool
    {
        return $subject->getSubmittedAt() !== null
            && $subject->getWordCount() >= 20
            && !$subject->isFlagged();
    }
}

Register with the tag the bundle's compiler pass looks for:

# config/services.yaml
services:
    _defaults:
        autowire: true
        autoconfigure: true

    App\Rules\:
        resource: '../src/Rules/'
        tags: ['vouchedfor.rules.rule']   # confirm exact tag in the compiler pass

With autoconfigure: true, if the interface is properly wired for autoconfiguration, the tag is applied for you — check src/DependencyInjection/CompilerPass/ to confirm.

Evaluate via the injected registry, not by hand. The point of the bundle is that you don't new rules or iterate over them yourself. Inject the evaluator/registry service and pass the subject:

public function __construct(private RuleEvaluator $rules) {}

public function __invoke(Review $review): Response
{
    $violations = $this->rules->evaluate($review); // collection of failed rules
    // map to form errors / API problem JSON / a 422
}

Use it as a domain guard, not a form validator. The strongest pattern is calling the rule set in a command handler or an entity lifecycle listener so the same policy is applied whether the request came from HTTP, a queue worker, or an artisan/console command. Keep the rules pure and inject anything stateful (clock, config, repository lookups) into the rule's constructor.

Test rules in isolation. Rules should be constructible with mocks and evaluated without a kernel. If evaluating a rule requires a booted container, the design has leaked and you'll pay for it in test runtime. Write a small data provider of subject => expected outcome cases; that's the bulk of the value of a rules engine.

Compose sparingly. If the bundle supports and/or/not composites, use them only for genuinely orthogonal checks. Beyond two levels, a composite becomes unreadable and a flat list of named rules reads far better in logs and error messages.

Integration tip: if you need to enrich a subject before evaluation, do it in the caller, not inside a rule — rules that reach into repositories become untestable and slow.

Gotchas and Tips

  • Bundle is Symfony-only. There is no Laravel service provider, facade, or config publishing. Porting means rewriting the container wiring; the rule logic itself usually transplants cleanly into an app/Rules namespace bound via a singleton() in a service provider.
  • Empty or missing config. Many small bundles register an extension that throws if a required config key is absent. Run bin/console config:dump-reference <alias> to see the actual key names before guessing YAML.
  • Compiler-pass caching is the #1 debugging trap. After changing tags or rule classes, bin/console cache:clear. A rule that "isn't being called" is almost always an untagged service silently excluded from the registry.
  • Inspect the container, don't guess. bin/console debug:container --tag=<tag> and debug:container <service-id> tell you in seconds whether your rule made it into the registry and whether the service is public.
  • Tag name must match exactly. Autoconfiguration only applies if the interface is registered with registerForAutoconfiguration in the bundle's extension; otherwise add the tag by hand.
  • support/supports guards are easy to omit. Without a supports() check, a registry iterating all rules over all subjects gives you silent false positives.
  • No maintenance signal. 2 stars and 0 dependents means no upstream fixes. Pin the exact version ("vouchedfor/rules-bundle": "1.0.*" or a commit hash), and if you depend on it heavily, fork it into your own vendor namespace — it's small enough to vendor.
  • Extension points worth knowing: the rule interface (add your own implementations), the evaluator service (decorate it to add logging or caching of compiled results), and — if it wraps symfony/expression-language — ExpressionFunctionProviderInterface for custom domain functions.
  • Performance: evaluate rules against an already-loaded subject; avoid rules that trigger lazy Doctrine collection loads. If a rule set is evaluated per row in a loop, compile/cache the rule list once outside the loop.
  • Log which rule failed, not just that evaluation failed. Wrap the evaluator and record rule class names in your failure payload — it's the difference between a five-minute and a two-hour debugging session.
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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib