Weave Code
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

Laravel Fluent Validation Laravel Package

sandermuller/laravel-fluent-validation

Type-safe, IDE-autocomplete Laravel validation rule builders. Create rules fluently without memorizing strings; each rule exposes only valid methods. Define nested array validation with each()/children(). Optional HasFluentRules trait speeds wildcard validation dramatically (up to 160x).

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require sandermuller/laravel-fluent-validation
    

    Requires PHP 8.2+ and Laravel 11+.

  2. Basic Usage in Form Request: Replace traditional validation strings with fluent builders in your rules() method:

    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()->required()->unique('users'),
            ];
        }
    }
    
  3. Key First Use Case: Convert a simple validation rule from string syntax to fluent syntax:

    // Before
    'name' => 'required|string|min:3|max:255',
    
    // After
    'name' => FluentRule::string('Name')->required()->min(3)->max(255),
    

Implementation Patterns

Core Workflows

  1. Fluent Rule Chaining: Chain methods for each validation rule type (string, email, date, etc.):

    FluentRule::string('Full Name')
        ->required()
        ->min(2)
        ->max(255)
        ->message('Must be between 2 and 255 characters')
    
  2. Conditional Rules: Use when() for dynamic rules:

    FluentRule::string('Role')
        ->when($isAdmin, fn ($r) => $r->required()->in(['admin', 'editor']))
    
  3. Array Validation: Validate nested arrays with each() and children():

    FluentRule::array('Items')
        ->each([
            'id'   => FluentRule::integer()->required(),
            'name' => FluentRule::string()->max(255),
        ])
    
  4. Database Rules: Use unique() and exists() with closures for dynamic conditions:

    FluentRule::email()
        ->required()
        ->unique('users', 'email', fn ($r) => $r->ignore($userId))
    

Integration Tips

  1. Form Requests: Extend FluentFormRequest or use HasFluentRules trait:

    class StorePostRequest extends FluentFormRequest { ... }
    
  2. Custom Messages: Attach labels and messages directly to rules:

    FluentRule::string('Title')->required()->message('Title is required')
    
  3. Type Safety: Use FluentRuleContract for return type hints:

    /** @return array<string, FluentRuleContract> */
    public function rules(): array { ... }
    
  4. Performance Optimization: For large arrays, use HasFluentRules trait for O(n) wildcard validation.

  5. Testing: Use FluentRulesTester for validation tests:

    $this->validateRules($request, [
        'title' => FluentRule::string()->required(),
    ]);
    

Gotchas and Tips

Common Pitfalls

  1. Static Factory Misuse: FluentRule is a static factory, not a base class. Each type returns a specific rule class:

    // Correct
    FluentRule::string()->required();
    
    // Incorrect (returns StringRule, not FluentRule)
    FluentRule::string()->email(); // Throws error
    
  2. Array Validation Scope: each() applies to wildcard arrays (items.*), while children() applies to fixed keys:

    // Wildcard (items.*.name)
    FluentRule::array()->each(FluentRule::string()->max(255));
    
    // Fixed key (items.fixed_key)
    FluentRule::array()->children(['fixed_key' => FluentRule::string()]);
    
  3. Message Desync: Labels and messages are tied to the rule instance. Avoid separate attributes() or messages() arrays.

  4. Performance Caveats:

    • Wildcard validation is O(n²) in Laravel's native validator; HasFluentRules optimizes to O(n).
    • Database exists/unique checks batch into single queries for wildcards.

Debugging Tips

  1. IDE Autocompletion: Use IDE hints for available methods (e.g., FluentRule::string() won’t suggest digits()).

  2. Rule Inspection: Use RuleSet for debugging complex rules:

    $ruleSet = new RuleSet($rules);
    $ruleSet->inspect('title'); // Inspect a specific rule
    
  3. PHPStan Errors:

    • Write tests for runtime bugs (e.g., wrong argument types).
    • Skip tests for static-only issues (e.g., missing PHPDoc).
  4. Migration Issues:

Extension Points

  1. Custom Rules: Extend FluentRule or create macros:

    FluentRule::macro('customRule', function () {
        return $this->rule(['custom_rule']);
    });
    
  2. Livewire Integration: Use HasFluentValidation trait for Livewire components:

    use SanderMuller\FluentValidation\Livewire\HasFluentValidation;
    
  3. Performance Tuning:

    • Pre-evaluate rules with whenInput() for dynamic branching.
    • Use rule() for Laravel-specific escape hatches (e.g., authorization).
  4. Static Analysis: Enable the PHPStan rules package to catch unbounded each() chains.

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.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor