Laravel Validate by Milwad Khosravi
CommunityThe Laravel-Validate-Filament package brings Laravel-Validate’s custom rules to Filament forms as fluent field methods for simplified and efficient form validation
Author:
Milwad Khosravi
Package health
Automated checks of this plugin's Composer package
15 checks
- Passed: GitHub Actions pinned to SHA
- Skipped: GitLab CI includes pinned to SHA
- Passed: Open security advisories
- Passed: Dependabot PR responsiveness — No open Dependabot PRs.
- Skipped: Renovate MR responsiveness
- Passed: Dependabot or Renovate configured
- Passed: Dependency update cooldown configured
- Passed: Provides a security policy
- Passed: Abandoned or archived — No consulted source marks the package abandoned (packagist, github).
- Passed: Commit and release recency — Active: last commit 0 days ago; last release 10 days ago.
-
Passed:
composer.lock not committed by library
—
composer.lockis absent from the released dist archive. - Passed: Dist archive is lean
-
Passed:
Current Laravel version supported
—
Package dependencies resolve together with current Laravel
13.0. -
Passed:
Current PHP version supported
—
Constraint
^8.1supports current PHP8.5. - Skipped: Current Symfony version supported
filament/
namespace. Review the source and install at your own risk. Found
malware or an unresolved security issue the author won't
address?
Report it
.
Documentation
- Contents
- Requirements
- Installation
- Usage
- Available macros
- How it works
- Troubleshooting
- Roadmap
- Testing
- Contributing
- Security
- Credits
- Changelog
- License
40+
laravel-validaterules as fluent, chainable Filament field methods — no customRuleobjects, norule()boilerplate.
laravel-validate-filament registers a macro for every rule in milwad/laravel-validate on Filament's base Field, so you can validate phone numbers, IBANs, national cards, strong passwords, slugs, hex colors and more by chaining a single method — the same way you already chain ->required() or ->email():
use Filament\Forms\Components\TextInput;
use Milwad\LaravelValidate\Utils\Country;
TextInput::make('phone')->validPhoneNumber(Country::IRAN),
TextInput::make('iban')->validIban([Country::IRAN, Country::GERMANY]),
TextInput::make('color')->validHexColor(),
TextInput::make('slug')->validSlug(),
Without this package you would wire each rule up by hand on every field:
// Before
use Milwad\LaravelValidate\Rules\ValidPhoneNumber;
TextInput::make('phone')->rule(new ValidPhoneNumber(Country::IRAN)),
// After
TextInput::make('phone')->validPhoneNumber(Country::IRAN),
#Contents
- Requirements
- Installation
- Validation messages
- Usage
- Available macros
- How it works
- Troubleshooting
- Roadmap
- Testing
- Contributing
- Security
- Credits
- Changelog
- License
#Requirements
| Package | Versions |
|---|---|
| PHP | 8.1+ |
| Laravel | 10, 11, 12, 13 |
| Filament | 3, 4, 5 |
#Installation
composer require milwad/laravel-validate-filament
The service provider is auto-discovered. It registers a macro for each rule on Filament\Forms\Components\Field, so the macros work on every field: TextInput, Textarea, Select, DatePicker, ...
#Validation messages
Error messages come from milwad/laravel-validate. Publish the language file for your locale, otherwise the raw translation key (for example validate.hex-color) is shown:
php artisan vendor:publish --tag="validate-lang-en"
Replace en with your language. See the supported languages.
#Usage
Every macro is named after its rule class (ValidPhoneNumber → validPhoneNumber()). The valid prefix keeps them from clashing with Filament's own methods such as url(), uuid() or hexColor(). Because the macros live on the base Field class, they chain with any field type (TextInput, Textarea, Select, DatePicker, ...) and compose freely with Filament's own methods.
#A complete form
A typical Filament resource form using several macros side by side with native Filament rules:
use Filament\Forms\Components\TextInput;
use Filament\Forms\Form;
use Milwad\LaravelValidate\Utils\Country;
public function form(Form $form): Form
{
return $form->schema([
TextInput::make('username')
->required()
->validUsername(),
TextInput::make('phone')
->required()
->validPhoneNumber(Country::IRAN),
TextInput::make('iban')
->validIban([Country::IRAN, Country::GERMANY]),
TextInput::make('password')
->password()
->validStrongPassword(),
TextInput::make('website')
->validUrl(),
TextInput::make('slug')
->validSlug(),
]);
}
#Conditional rules
Like Filament's rule(), every macro accepts a $condition as its last argument:
TextInput::make('national_card')
->validNationalCard(condition: fn (Get $get) => $get('country') === 'IR'),
#Dynamic arguments
Arguments can be closures. Filament evaluates them at validation time, with its usual dependency injection:
Select::make('country')
->options(['IR' => 'Iran', 'DE' => 'Germany'])
->live(),
TextInput::make('phone')
->validPhoneNumber(fn (Get $get) => $get('country')),
#Custom error messages
Error messages come from the milwad/laravel-validate rule classes. To change the wording, publish that package's language file and edit the relevant key (see Validation messages):
php artisan vendor:publish --tag="validate-lang-en"
// lang/vendor/validate/en/validate.php
'hex-color' => 'The :attribute must be a valid hex color (e.g. #fcba03).',
Edits there apply everywhere the rule is used, in Filament forms and in ordinary Laravel validation alike.
#Masked display in tables and infolists
To show sensitive values without revealing them in full, the package also adds three display macros to TextColumn (tables) and TextEntry (infolists). They are registered only when filament/tables or filament/infolists is installed.
use Filament\Infolists\Components\TextEntry;
use Filament\Tables\Columns\TextColumn;
TextColumn::make('iban')->maskedIban(); // IR06 **** **** **** **** **00 01
TextColumn::make('card_number')->maskedCardNumber(); // **** **** **** 1111
TextEntry::make('national_card')->masked(end: 4); // ******6437
TextEntry::make('phone')->masked(start: 4, end: 2); // 0912*****89
| Macro | Arguments | Shows |
|---|---|---|
maskedIban() |
— | Country code, check digits and last 4 characters, in groups of 4 |
maskedCardNumber() |
— | Last 4 digits, in groups of 4 |
masked() |
int $start = 0, int $end = 4, string $character = '*' |
The first $start and last $end characters |
Like the field macros, each one takes bool|Closure $condition = true as its last argument, so you can show the full value to some users only:
TextColumn::make('iban')->maskedIban(fn () => ! auth()->user()->can('view-full-iban'));
Every argument can be a closure. Spaces and dashes in IBANs and card numbers are ignored, and a value too short to hide anything is masked entirely. Each macro sets the component's formatStateUsing(), so it replaces any formatter set earlier in the chain (and a later formatStateUsing() replaces the mask).
Masking only changes what is displayed. It is not access control: the full value is still in your database, and features such as copyable(), search or exports may use the raw value. Hide or restrict those where it matters.
#IDE autocompletion
Macros are added at runtime, so your IDE can't see them on its own. Generate a helper file with a @method annotation for every macro:
php artisan laravel-validate-filament:ide-helper
This writes _ide_helper_laravel_validate_filament.php to your project root. PhpStorm, VS Code (Intelephense), PHPStan and Psalm pick it up automatically, so TextInput::make('iban')->validIban(...) and TextColumn::make('iban')->maskedIban() autocomplete with their arguments. Pass a filename to put it somewhere else (php artisan laravel-validate-filament:ide-helper .ide/filament-validate.php), re-run it after upgrading the package, and add the file to .gitignore if you'd rather not commit it.
#Available macros
| Macro | Arguments | Rule |
|---|---|---|
validBase64() |
ValidBase64 |
|
validBitcoinAddress() |
ValidBitcoinAddress |
|
validCamelCase() |
ValidCamelCase |
|
validCapitalCharWithNumber() |
ValidCapitalCharWithNumber |
|
validCarNumber() |
ValidCarNumber |
|
validCartNumberIran() |
ValidCartNumberIran |
|
validCountry() |
bool $validByKey = false |
ValidCountry |
validCreditCard() |
ValidCreditCard |
|
validDiscordUsername() |
ValidDiscordUsername |
|
validDomain() |
ValidDomain |
|
validDuplicate() |
ValidDuplicate |
|
validDuplicateCharacter() |
ValidDuplicateCharacter |
|
validEvenNumber() |
ValidEvenNumber |
|
validHashtag() |
ValidHashtag |
|
validHexColor() |
ValidHexColor |
|
validHtmlTag() |
ValidHtmlTag |
|
validIban() |
array|string $countries = [] |
ValidIban |
validImei() |
ValidImei |
|
validIpAddressIPV4() |
ValidIpAddressIPV4 |
|
validIpAddressIPV6() |
ValidIpAddressIPV6 |
|
validIranPostalCode() |
ValidIranPostalCode |
|
validJalaliDate() |
string $character = '/' |
ValidJalaliDate |
validJwt() |
ValidJwt |
|
validKebabCase() |
ValidKebabCase |
|
validLandlineNumber() |
?string $code = null |
ValidLandlineNumber |
validLatitude() |
ValidLatitude |
|
validLongitude() |
ValidLongitude |
|
validNameDaysWeek() |
ValidNameDaysWeek |
|
validNationalCard() |
ValidNationalCard |
|
validNoHtml() |
bool $strict = false |
ValidNoHtml |
validOddNumber() |
ValidOddNumber |
|
validPascalCase() |
ValidPascalCase |
|
validPattern() |
int $length, string $separator = '-' |
ValidPattern |
validPhoneNumber() |
?string $code = null |
ValidPhoneNumber |
validPort() |
ValidPort |
|
validSlashEndOfString() |
ValidSlashEndOfString |
|
validSlug() |
ValidSlug |
|
validSnakeCase() |
ValidSnakeCase |
|
validStrongPassword() |
ValidStrongPassword |
|
validUlid() |
ValidUlid |
|
validUrl() |
ValidUrl |
|
validUsername() |
ValidUsername |
|
validUuid() |
ValidUuid |
|
validVatId() |
ValidVatId |
Every macro also takes bool|Closure $condition = true as its last argument. Country codes are available as constants on Milwad\LaravelValidate\Utils\Country. For details on each rule, see the laravel-validate docs.
#How it works
On boot, the package's service provider calls FieldMacros::register(), which loops over every laravel-validate rule and registers a macro on Filament\Forms\Components\Field. Each macro simply forwards to Filament's rule() method with a fresh rule instance, so there is no runtime overhead beyond the rules you actually use, and nothing to configure. Rules that take constructor arguments (validIban, validPhoneNumber, ...) accept those arguments — and closures in their place — and resolve them with Filament's evaluate() at validation time.
DisplayMacros::register() does the same for Filament\Tables\Columns\TextColumn and Filament\Infolists\Components\TextEntry, skipping either one if its package isn't installed. Each display macro sets a formatStateUsing() callback that runs the value through Milwad\LaravelValidateFilament\Mask, which you can also call directly (Mask::iban($value), Mask::cardNumber($value), Mask::middle($value, 0, 4)).
#Troubleshooting
A macro method is not found (Method ... does not exist). Make sure the package is installed and its service provider is discovered (composer require milwad/laravel-validate-filament, then php artisan package:discover if you have disabled auto-discovery). The macros are only registered once the service provider boots.
The error message shows a raw key like validate.hex-color. Publish the milwad/laravel-validate language file for your locale so the key resolves to real text — see Validation messages and Custom error messages. The wording lives in the rule's translation file, not in Filament's per-field validationMessages(), so edit it there.
Validation does not run on an empty field. Like Laravel's own rules, these run only when a value is present. Chain ->required() when the field must not be empty.
#Roadmap
v1 ships field macros, masked display macros and an IDE helper. Planned for next versions:
- Ready-made field components for the most common rules, e.g.
PhoneNumberInput::make('phone'),IbanInput::make('iban'),NationalCardInput::make('national_card'),StrongPasswordInput::make('password'), each with the rule applied plus sensible defaults (mask, placeholder, prefix icon, input mode). - Translated error messages out of the box, without having to publish the
milwad/laravel-validatelanguage files. - IDE autocompletion for the macros — see IDE autocompletion.
- Table column / infolist helpers for masked display — see Masked display in tables and infolists.
- Keep the macro list in sync when
milwad/laravel-validateadds new rules.
#Testing
composer test
The suite runs against the Laravel and Filament versions listed in Requirements via Orchestra Testbench. If you are contributing a change, install dev dependencies first:
composer install
composer test
#Contributing
Contributions are welcome. A good change is small, focused, and comes with a test.
- Fork the repository and create a branch off
1.x. - Run
composer install. - Make your change. New or changed behaviour needs a passing test under
tests/. - Run
composer testand make sure the suite is green. - Open a pull request describing what changed and why.
If you are adding support for a new milwad/laravel-validate rule, register its macro in src/FieldMacros.php — a no-argument rule goes in the SIMPLE_RULES list, a rule with constructor arguments gets its own entry in rulesWithArguments() — and add a row to the Available macros table.
#Security
If you discover a security vulnerability, please do not open a public issue. Email the author at [email protected] instead. All reports will be reviewed and addressed promptly.
#Credits
- Milwad Khosravi — author
- milwad/laravel-validate — the validation rules this package exposes
- All contributors
#Changelog
See the Releases page for the list of changes in each version.
#License
The MIT License (MIT). See LICENSE.
Featured Plugins
A selection of plugins curated by the Filament team
Soft Theme
A theme that gives panels a warm, approachable look with rounded shapes, gentle colors, and serif headings.
Filament
Advanced Tables (formerly Filter Sets)
Supercharge your tables with powerful features like user-customizable views, quick filters, multi-column sorting, advanced table searching, convenient view management, and more. Compatible with Resource Panel Tables, Relation Managers, Table Widgets, and Table Builder!
Kenneth Sese
Spotlight Pro
Browse your Filament Panel with ease. Filament Spotlight Pro adds a Spotlight like Command Palette to your Filament Panel.
Dennis Koch