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 Setup

  1. Installation: Add via Composer:

    composer require sandermuller/laravel-fluent-validation
    

    Requires PHP 8.2+ and Laravel 11+.

  2. First Use Case: Replace a simple string validation in a Form Request:

    use SanderMuller\FluentValidation\FluentRule;
    
    public function rules(): array
    {
        return [
            'name' => FluentRule::string('Full Name')->required()->min(2)->max(255),
        ];
    }
    
  3. Key Files to Explore:

    • src/FluentRule.php: Entry point for all rule builders.
    • src/Contracts/FluentRuleContract.php: Base contract for type-hinting.
    • src/HasFluentRules.php: Trait for Form Requests.

Implementation Patterns

Core Workflow

  1. Rule Chaining: Build rules fluently with IDE autocompletion:

    FluentRule::email('Email Address')
        ->required()
        ->unique('users', 'email', fn ($r) => $r->ignore($id))
        ->message('Please provide a valid email.');
    
  2. Array Validation:

    • Wildcard Arrays: Use each() for dynamic keys:
      'items' => FluentRule::array()->each([
          'id'   => FluentRule::integer()->required(),
          'name' => FluentRule::string()->max(255),
      ]),
      
    • Fixed-Key Arrays: Use children() for static keys:
      'metadata' => FluentRule::array()->children([
          'author' => FluentRule::string(),
          'tags'   => FluentRule::array(),
      ]),
      
  3. Conditional Rules:

    'role' => FluentRule::string()->when(
        $isAdmin,
        fn ($r) => $r->required()->in(['admin', 'editor']),
        fn ($r) => $r->nullable()
    ),
    
  4. Form Request Integration:

    • Add HasFluentRules trait or extend FluentFormRequest:
      use SanderMuller\FluentValidation\FluentFormRequest;
      
      class StorePostRequest extends FluentFormRequest { ... }
      
  5. Testing:

    • Use FluentRulesTester for assertions:
      $this->assertValidationRules(
          FluentRule::string()->required(),
          ['name' => '']
      )->fails();
      

Integration Tips

  • Livewire: Use HasFluentValidation trait for component validation.
  • Filament: Override validate() in resources/forms to use FluentRule.
  • Performance: For large arrays (e.g., CSV imports), HasFluentRules optimizes wildcard validation up to 160x faster via tree-walking.
  • Database Queries: Batch exists()/unique() checks into single whereIn queries for wildcard arrays.

Gotchas and Tips

Pitfalls

  1. Static Factory Misuse:

    • FluentRule is a static factory, not a base class. Avoid instantiating it directly:
      // ❌ Wrong
      $rule = new FluentRule();
      
      // ✅ Correct
      $rule = FluentRule::string();
      
  2. Type-Hinting:

    • Use FluentRuleContract for return type hints, not concrete classes:
      /** @return array<string, FluentRuleContract> */
      public function rules(): array { ... }
      
  3. Nested Arrays:

    • Wildcard children (each()) must be defined under their parent. Avoid mixing each() and children() for the same key:
      // ❌ Ambiguous
      'items' => FluentRule::array()->each([
          '*.name' => FluentRule::string(), // Invalid syntax
      ]),
      
      // ✅ Correct
      'items' => FluentRule::array()->each([
          'name' => FluentRule::string(),
      ]),
      
  4. Database Rule Chaining:

    • Closures for unique()/exists() must return the rule, not a void:
      // ❌ Silent failure
      ->unique('users', fn ($r) => $r->ignore($id))
      
      // ✅ Correct
      ->unique('users', 'email', fn ($r) => $r->ignore($id))
      
  5. Label Overrides:

    • Labels apply to the entire rule chain. Redefine labels for nested rules:
      'user' => FluentRule::object()->children([
          'name' => FluentRule::string('User Name')->required(),
      ]),
      

Debugging Tips

  1. Error Messages:

    • Use ->message() or ->messageFor() for custom messages:
      ->message('The :attribute must be at least 2 characters.')
      ->messageFor('min', 'Custom min error.')
      
  2. Validation Inspection:

    • Use RuleSet::build() to inspect rules before validation:
      $ruleSet = RuleSet::build($this->rules());
      dd($ruleSet->toArray());
      
  3. Performance Profiling:

    • Enable FluentValidation\Performance\Benchmark in config/fluent-validation.php to log validation times.
  4. PHPStan Integration:

    • Install the companion package sandermuller/laravel-fluent-validation-phpstan to detect unbounded each() chains:
      composer require --dev sandermuller/laravel-fluent-validation-phpstan
      

Extension Points

  1. Custom Rules:

    • Extend FluentRule via macros:
      FluentRule::macro('customRule', function () {
          return Rule::custom(fn ($attribute, $value) => $value === 'secret');
      });
      
    • Use in validation:
      FluentRule::string()->customRule()->required()
      
  2. Rule Composers:

    • Group reusable rules:
      $emailRule = FluentRule::email()->required()->unique('users');
      $rules['email'] = $emailRule;
      
  3. Livewire/Filament:

    • Override validation in components:
      public function rules(): array
      {
          return [
              'field' => FluentRule::string()->when(
                  $this->isAdmin(),
                  fn ($r) => $r->required(),
                  fn ($r) => $r->nullable()
              ),
          ];
      }
      
  4. Migrating Legacy Code:

    • Use the companion Rector package to automate bulk conversion:
      composer require --dev sandermuller/laravel-fluent-validation-rector
      vendor/bin/rector process src --dry-run
      

Config Quirks

  1. Default Labels:

    • Set default labels in config/fluent-validation.php:
      'default_labels' => [
          'email' => 'Email Address',
      ],
      
  2. Performance Mode:

    • Enable optimize_for_performance in config for large datasets:
      'optimize_for_performance' => env('FLUENT_VALIDATION_PERF_MODE', false),
      
  3. Message Fallbacks:

    • Configure fallback messages for unsupported rules:
      'fallback_messages' => [
          'custom' => 'The :attribute does not meet the requirements.',
      ],
      
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.
nasirkhan/laravel-sharekit
directorytree/privacy-filter-classifier
directorytree/privacy-filter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony