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

Rulerz Bundle Laravel Package

wallabag/rulerz-bundle

A Symfony bundle that integrates the RulerZ rule engine, letting you express business rules and filters in a readable DSL and apply them to Doctrine entities or collections. Useful for building dynamic specifications, query filters, and reusable rule-based logic in Symfony applications.

View on GitHub
Deep Wiki
Context7

Getting Started

This is the Symfony integration layer for kphoen/rulerz (the wallabag fork). You almost never install this bundle for its own sake — you install it when you want the RulerZ rule engine auto-wired into a Symfony service container so you can filter Doctrine queries, arrays, or other "targets" with a string rule like points > 100 and group in :groups.

  1. Install alongside RulerZ itself:

    composer require wallabag/rulerz-bundle kphoen/rulerz
    
  2. Register the bundle. On Symfony 4+/Flex add it to config/bundles.php:

    RulerZ\RulerZBundle::class => ['all' => true],
    

    On older Symfony add it to app/AppKernel.php.

  3. Enable/configure it in config/packages/rulerz.yaml (defaults are usually fine):

    rulerz:
        cache: null          # PSR-6/PSR-16 cache service or null
        debug: '%kernel.debug%'
    
  4. Look first for the rulerz service (type-hint RulerZ\RulerZ or the underlying executor). Do not instantiate RulerZ manually — the bundle gives you a configured instance with the compilers/cache it supports.

  5. First use case — filter a Doctrine QueryBuilder from a repository with a user-supplied rule string:

    use RulerZ\RulerZ;
    
    public function activeAdmins(RulerZ $rulerz, string $rule): array
    {
        $qb = $this->createQueryBuilder('u');
    
        return $rulerz->filterSpec($qb, $rule)... // or $rulerz->filter($qb, $rule)
    }
    

    filter()/matching() on a QueryBuilder returns the builder with the rule applied (not executed), so you keep control over pagination and hydration. On raw arrays, filter() returns the filtered array directly.

Implementation Patterns

Rules as a feature, not a gimmick. The highest-value day-to-day pattern is letting users (or config files) express filters as rules instead of writing a switch over filter columns. Keep the rule string in a form field or database column, pass it to rulerz, and bind parameters separately:

$rulerz->filter($target, 'status = :status and score >= :min', [
    'status' => 'active',
    'min'    => 50,
]);

Target the right abstraction. RulerZ dispatches on the target type, so the same rule string can run against:

  • a Doctrine QueryBuilder (translator returns SQL, stays in the DB — the pattern you want for lists/pagination),
  • a PHP array (in-memory filtering; fine for small fixtures, tests, or cached result sets),
  • other compilers if installed (Elasticsearch, Pomm, etc.).

Design your service around "a target plus a rule," and keep the target choice in the caller so the same rule can be reused across storage layers.

Specifications for reusable business rules. Encapsulate non-trivial rules as spec classes and inject them, rather than scattering rule strings:

final class IsActiveSpec implements \RulerZ\Spec\Specification
{
    public function getRule(): string
    {
        return 'status = :status';
    }

    public function getParameters(): array
    {
        return ['status' => 'active'];
    }
}

Call $rulerz->satisfiesSpec($entity, $spec) for single-entity checks and filterSpec()/matchingSpec() for collections. This keeps named business rules testable and greppable, and avoids user-entered strings where none are needed.

Compose with the container. Type-hint RulerZ\RulerZ in services and controllers; the bundle's service is shared and already has compilers registered. Tag spec services (e.g. rulerz.specification) where supported so they can be collected and exposed by name in an admin UI, a "saved filters" feature, or a config-driven rule set.

Combine with the form/query layer. Typical workflow: a filter DTO → a rule string + parameters → matching() on a QueryBuilder → paginate. This lets you expose a "rule editor" (advanced search) without writing a query builder per field, and it keeps the rule portable to an array target for unit tests.

Cache parsed rules. Enable a cache adapter in dev/prod config when rules come from user input; RulerZ parses the rule string on every call, and a PSR cache removes repeated parsing in request-heavy paths (e.g. per-row satisfies() checks in a Twig loop — better still, pre-filter the collection).

Gotchas and Tips

  • Maintenance status is the first gotcha. This is a wallabag fork with effectively no downstream dependents and near-zero stars. Pin the version in composer.json, and check that its kphoen/rulerz constraint and Symfony version constraints match your stack before adopting. If you are not already inside the wallabag ecosystem, weigh kphoen/rulerz-bundle (or wiring RulerZ manually) first.
  • filter() vs matching() semantics differ by target. On a QueryBuilder you get the builder back to further modify; on arrays you get results. Do not assume chaining works identically across targets — assert the return type in tests.
  • Parameters are not interpolated for you. Rules are parsed and compiled; named placeholders must be supplied in the parameters array with matching names. A missing parameter typically surfaces as a compilation/Doctrine error, not a helpful "unknown parameter" message.
  • User-supplied rules need an allowlist. RulerZ does not execute PHP, but unrestricted field names, operators, and in-style lists can leak schema details or produce expensive queries. Validate allowed identifiers/operators before handing a string to the engine, and always bind values as parameters.
  • Hydration and entity targets. satisfies() on a managed Doctrine entity works in memory; on a QueryBuilder it compiles to SQL. Mixing the two inside one code path (e.g., checking a proxied entity before flush) is a common source of confusing results.
  • Cache config quirks. The bundle's cache option expects a service reference/ID, not an inline adapter class. Passing true or a raw DSN will fail during container compilation; leave it null in tests to avoid stale parsed-rule state.
  • Debugging rules. Turn on the bundle's debug flag in dev to get clearer parser errors, and keep rule strings in one place (specs or a config file) so a failing rule is easy to isolate. When a rule "silently matches nothing," check the parameter types first — string "1" vs int 1 in Doctrine conditions bites often.
  • Extension points. The bundle's real leverage is the tagged-specification collection and the configured executor; if you need a custom target type, register a RulerZ compiler in your own service and pass it to the executor rather than forking the bundle.
  • Test without the container where possible. Instantiate RulerZ against the array target in unit tests; reserve the bundle's service for integration tests so parser behavior is covered without booting Doctrine.
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.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route