sandermuller / laravel-fluent-validation
Fluent validation rule builders for Laravel
Package info
github.com/SanderMuller/laravel-fluent-validation
pkg:composer/sandermuller/laravel-fluent-validation
Fund package maintenance!
Requires
- php: ^8.2
- illuminate/contracts: ^12.0||^13.0
- illuminate/http: ^12.0||^13.0
- illuminate/support: ^12.0||^13.0
- illuminate/validation: ^12.0||^13.0
Requires (Dev)
- driftingly/rector-laravel: ^2.3
- larastan/larastan: ^3.9.3
- laravel/pao: ^1.1
- laravel/pint: ^1.29
- livewire/livewire: ^3.0||^4.0
- mrpunyapal/rector-pest: ^0.2.7
- nunomaduro/collision: ^8.0
- orchestra/testbench: ^10.11
- pestphp/pest: ^3.0||^4.4.5
- pestphp/pest-plugin-arch: ^3.0||^4.0
- pestphp/pest-plugin-laravel: ^3.0||^4.1
- phpstan/extension-installer: ^1.4.3
- phpstan/phpstan-deprecation-rules: ^2.0.4
- phpstan/phpstan-phpunit: ^2.0.16
- phpstan/phpstan-strict-rules: ^2.0.10
- rector/rector: ^2.4.1
- rector/type-perfect: ^2.1.2
- sandermuller/boost-skills: ^2.5
- sandermuller/package-boost-laravel: ^1.0
- spaze/phpstan-disallowed-calls: ^4.10
- symplify/phpstan-extensions: ^12.0.2
- tomasvotruba/cognitive-complexity: ^1.1
- tomasvotruba/type-coverage: ^2.1
Suggests
- nikic/php-parser: ^5.0 — required by SanderMuller\FluentValidation\Testing\Arch\BansFieldRuleTypeMethods, an opt-in Pest/PHPUnit arch helper that bans type-specific method calls on the untyped FluentRule::field() builder.
This package is auto-updated.
Last update: 2026-08-20 22:26:55 UTC
README
Fluent validation rule builders for Laravel
Write Laravel validation rules with IDE autocompletion instead of memorizing string syntax. Each rule type exposes only the methods that apply to it: FluentRule::string() won't offer digits(), FluentRule::date() won't offer mimes(). each() and children() keep parent and child rules in one place instead of scattered across dot-notation keys. For large arrays, the HasFluentRules trait makes wildcard validation up to 160x faster.
// Before 'name' => 'required|string|min:2|max:255', 'email' => ['required', 'email', Rule::unique('users')->ignore($id)], 'role' => Rule::when($isAdmin, 'required|string|in:admin,editor'), 'items' => 'array', 'items.*.id' => 'required|integer|exists:items,id', 'items.*.name' => 'required|string|max:255', // After 'name' => FluentRule::string('Full Name')->required()->min(2)->max(255), 'email' => FluentRule::email('Email')->required()->unique('users', 'email', fn ($r) => $r->ignore($id)), 'role' => FluentRule::string()->when($isAdmin, fn ($r) => $r->required()->in(['admin', 'editor'])), 'items' => FluentRule::array()->each([ 'id' => FluentRule::integer()->required()->exists('items', 'id'), 'name' => FluentRule::string()->required()->max(255), ]),
Migrating an existing codebase? Jump straight to Migrating to fluent validation; a companion package automates the bulk of the rewrite.
Installation
You can install the package via composer:
composer require sandermuller/laravel-fluent-validation
Requires PHP 8.2+ and Laravel 12+. See Installation for AI-assisted development with Laravel Boost, and UPGRADING.md when upgrading from an older release.
Usage
Add the HasFluentRules trait to your form request:
use Illuminate\Foundation\Http\FormRequest; use SanderMuller\FluentValidation\FluentRule; use SanderMuller\FluentValidation\HasFluentRules; class StorePostRequest extends FormRequest { use HasFluentRules; public function rules(): array { return [ 'title' => FluentRule::string('Title')->required()->min(2)->max(255), 'email' => FluentRule::email('Email')->required()->unique('users'), 'date' => FluentRule::date('Publish Date')->required()->afterToday(), 'avatar' => FluentRule::image()->nullable()->max('2mb'), 'tags' => FluentRule::array(label: 'Tags')->required()->each( FluentRule::string()->max(50) ), 'password' => FluentRule::password()->required()->mixedCase()->numbers(), ]; } }
The label 'Title' replaces :attribute in error messages. You get "The Title field is required" instead of "The title field is required", without a separate attributes() array.
See Basic usage for the schema() builder, typing your rules() return, and using fluent rules outside form requests.
Documentation
Read the full documentation at sandermuller.github.io/laravel-fluent-validation.
Getting started
- Why this package? — DX, type safety, structure, performance, and how it compares to Laravel's
Ruleclass - Installation
- Basic usage — form requests, typing
rules(), theschema()builder, other contexts - Error messages — labels, per-rule messages
- Array validation —
each(),children(), nesting
Digging deeper
- Extending parent rules — child form requests,
modifyEach,modifyChildren, returning aRuleSet - Livewire —
HasFluentValidationtrait, Filament workaround - Performance — O(n) wildcards, pre-evaluation, fast-check closures, batched DB, benchmarks
- RuleSet — build, compose, inspect, validate, escape hatches, method reference
- Testing —
FluentRulesTester, Pest expectations - Rule reference — all types, modifiers, conditionals, macros
Migration and tooling
- Migrating to fluent validation — incremental migration and the automated Rector companion
- Static analysis with PHPStan — opt-in PHPStan rules package that flags unbounded
each()chains - Troubleshooting — common issues and solutions
Contributing
Please see CONTRIBUTING for details.
Changelog
Please see CHANGELOG for more information on what has changed recently.
Security vulnerabilities
Please review our security policy on how to report security vulnerabilities.
Credits
License
MIT License. Please see License File for more information.
