Skip to content

About

Type-safe fluent validation rule builders for Laravel, plus 39 rules for the formats Laravel has none for.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

156 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

laranail/validation

Tests Static analysis License: MIT

laranail/validation is not published to Packagist, so there is no registry-version badge to show: see Install.

Write Laravel validation rules with IDE autocompletion instead of memorising string syntax — each rule type exposes only the methods that apply to it, each() and children() keep parent and child rules in one place, and large wildcard arrays validate tens of times faster — see the benchmarks.

Targets PHP ^8.5 on Laravel ^13.

// 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),
]),

Install

composer require laranail/validation

Quick start guide and usage

Getting started

Nothing to configure: the service provider registers itself through package discovery and the builders work without publishing anything. Publish the config only for the global safety fuse or the opt-in string rule aliases:

php artisan vendor:publish --tag=laranail::validation-config

Usage

Add HasFluentRules to a form request and return fluent rules from rules(). The trait is what enables the optimized path — without it the builders still work, they just compile to ordinary Laravel rules.

use Illuminate\Foundation\Http\FormRequest;
use Simtabi\Laranail\Validation\FluentRule;
use Simtabi\Laranail\Validation\HasFluentRules;
use Simtabi\Laranail\Validation\Rules\Banking\Iban;

final class StorePayoutRequest extends FormRequest
{
    use HasFluentRules;

    public function rules(): array
    {
        return [
            'account' => FluentRule::string('Account')->required()->rule(new Iban()),
            'email'   => FluentRule::email()->required()->notDisposable(),
            'lines'   => FluentRule::array()->required()->max(50)->each([
                'sku'    => FluentRule::string()->required()->exists('products', 'sku'),
                'amount' => FluentRule::numeric()->required()->min(0.01),
            ]),
        ];
    }
}

$request->validated() returns the same shape it always did. For Livewire use HasFluentValidation; outside both, RuleSet::from([...])->check($data).

Documentation

Full documentation is at opensource.simtabi.com/documentation/laranail/validation.

Guides

  • Installation — Composer install, supported versions, optional Boost skills
  • Getting started — a form request end to end, then the same builders elsewhere
  • Configuration — the publishable config, opt-in string rule aliases, and the per-chain options
  • Architecture — builders, compiler, optimized execution, and why the fast path is safe
  • Performance — what makes it fast, the benchmarks, and when none of it helps
  • Comparison — how this differs from rule strings and Laravel's Rule class
  • Troubleshooting — common failure modes and their causes
  • Release — versioning, tagging, and the CI-managed changelog

Reference

  • Rule reference — every entry point, modifier, conditional, and macro hook
  • Rule library — the extended rules: IBAN, IMEI, postal codes, IP classification, and the rest
  • Phone rule — countries, line types, strictness, and E.164-normalised uniqueness
  • Person names — any number of name fields, several names in one field, and "at least one"
  • Identity and network fields — usernames, URLs, IP and MAC addresses, and the email additions
  • RuleSet — build, compose, inspect, export, and validate
  • Array validation — each() for wildcards, children() for fixed keys
  • Error messages — labels and per-rule messages on the rule itself
  • Livewire — the HasFluentValidation trait, plus Filament
  • Testing — FluentRulesTester and the Pest expectations
  • Static analysis — the opt-in arch test for untyped field() chains

Recipes

Project

Stability

2.0 states what SemVer covers. The stable surface is: FluentRule, FluentSchema, RuleSet (including its events and before()/after() hooks), the rule classes and their constructor signatures, the contracts (ClientCheckable, PrecognitionSkippable, TermList, FluentRuleContract), Check, Regex, Validation::fake(), RuleRegistrar, the console commands, and the laranail.validation.* config keys.

Everything marked @internal — the fast-check compiler, the optimizer validators, the batch machinery, everything under Internal\ — may change in a minor, and an arch test enforces the boundary. Build on the stable list; the optimizer is an implementation detail behind it.

Constrain to ^0.1 and read UPGRADING.md before moving between versions — rector-migrate-0.1.php auto-migrates the mechanical break (the service provider moved into Providers/), and rector-migrate-1.0.php still covers the 0.x one. Deprecations post-1.0 are marked @deprecated with the replacement and removal version, kept for at least one minor, and removed only in the next major. Behaviour-correcting fixes can still mean input an application previously accepted is now correctly rejected; UPGRADING calls those out.

Local development

composer install
composer test          # Pest
composer phpstan       # level max, 100% type coverage
composer format        # Pint
composer rector
php benchmark.php      # the optimizer's headline numbers

Tests run on Orchestra Testbench — there is no host application, so use vendor/bin/testbench rather than php artisan. Fixtures live under workbench/.

Sister packages

Package What it owns
laranail/atlas Country, currency and language data — and the rules over it
laranail/enumerator Enum values, names and transitions
laranail/chrono Timezones, date existence and ambiguity
laranail/toolkit Password strength and common-password rejection
laranail/captcha Turnstile, hCaptcha and reCAPTCHA
laranail/email Maintained disposable and role-account lists, and a production DNS resolver
laranail/package-tools The package scaffolding this one is built on

Email deliverability ships here as Rules\Network\DeliverableEmail, over a bundled cached resolver. laranail/email supplies maintained disposable-domain and role-account lists and a production resolver, replacing those fallbacks through the same contracts — installing it changes nothing you call.

Community

Questions and ideas belong in Discussions; bugs in Issues.

Credits

Originally written by Sander Muller, and maintained here under the laranail org with thanks to all contributors.

Contributing & security

Issues and PRs are welcome — see CONTRIBUTING.md. Report vulnerabilities per SECURITY.md (opensource@simtabi.com); participation follows the Code of Conduct.

License

MIT © Simtabi LLC. See LICENSE.

About

Type-safe fluent validation rule builders for Laravel, plus 39 rules for the formats Laravel has none for.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages