sandermuller/laravel-fluent-validation
Fluent validation rule builders for Laravel: write rules with IDE autocompletion instead of string syntax. Each rule type exposes only applicable methods, each() and children() keep parent and child rules together, and the HasFluentRules trait speeds up wildcard validation.
->rule([...])) for anything it doesn't model. Default position should be buy/adopt, not build — unless the runtime baseline rules it out.HasFluentRules trait claims up to 160x on nested wildcards and 62x on conditional-heavy payloads, plus batched exists/unique queries. That converts "imports and bulk-edit are slow" from a vague epic into a scoped, one-trait change — worth trialling before committing engineering to custom caching or chunking work.label(), message(), and fieldMessage() with the rule removes a real source of bugs: messages()/attributes() arrays drifting out of sync with rules(), and mis-ordered unique:users,email,$ignoreId,id arguments. Fewer QA cycles spent on error-copy correctness.FluentRule::string() won't offer digits()) reduce lookup time on a rule API most engineers touch rarely and remember poorly. Measurable through time-to-first-PR and review comment volume on form requests.each() chains) plus FluentRulesTester and Pest expectations let you set a static-analysis policy for validation, not just a style preference.Adopt when most of these hold:
min:5 ambiguity, Rule::when callables, scattered items.*.name keys.Look elsewhere when:
For executives (2 minutes): This is a low-cost, MIT-licensed developer-experience package for our Laravel validation layer. It makes validation rules typed and self-documenting, which shortens onboarding on a part of the codebase engineers touch rarely, and it removes a class of defects where error messages drift out of sync with the rules. It also claims significant speedups on our heaviest endpoints — bulk imports and multi-item forms. Cost is one engineer, one sprint, on a single module. Risk is a young dependency with a small user base, which we contain by piloting on one module with a pinned version rather than a codebase-wide rollout.
For engineering (5 minutes): FluentRule::string('Title')->required()->min(2)->max(255) replaces string rules, with each type exposing only its valid methods. each() and children() co-locate parent and child rules instead of scattering dot-notation keys. Labels and per-rule messages attach to the rule itself. HasFluentRules on a form request rewrites wildcard expansion as a single tree walk — the README claims up to 160x on nested wildcards — and batches exists/unique into one whereIn. There are companion Rector and PHPStan packages for migration and static enforcement, plus FluentRulesTester for tests. Escape hatch: ->rule([...]) takes any native rule.
Risks to state up front, not bury: small user base and no known dependents; a single maintainer; tight coupling to the Laravel major version; performance numbers are the author's own benchmarks and should be reproduced on our payloads, not taken on faith.
Ask: a one-sprint spike on the highest-volume form request or import endpoint, with three success criteria — a measurable latency improvement on that endpoint, a passing PHPStan run with the companion rules, and one engineer's verdict on authoring ergonomics versus string rules. Decision point at the end of the sprint: expand to a second module or stop and document why.
How can I help you explore Laravel packages today?