K

Formuláře

Validace formulářů

Pravidla na třech úrovních — pole, formulář a pipeline — a která z nich vyhrají, když se neshodnou.

Na této stránce

Wire Forms poskytuje validaci na třech úrovních: pravidla na úrovni pole, pravidla na úrovni formuláře a programová validace přes Core ValidationPipeline.


Pravidla na úrovni pole

Každé pole deklaruje svá vlastní validační pravidla:

TextInput::make('name')
->required()
->maxLength(255)
->rules(['string', 'regex:/^[a-zA-Z\s]+$/']);
 
TextInput::make('email')
->email()
->required()
->unique();
 
TextInput::make('age')
->numeric()
->rules(['integer', 'min:18', 'max:120']);
 
Select::make('role')
->required()
->rules('in:admin,editor,viewer');

Typové helpery nejsou validace

->email(), ->numeric(), ->integer(), ->url() a ->tel() jsou typové presety: nastaví HTML input typ a inputmode, což vybere klávesnici na telefonu a nechá prohlížeč nabídnout vlastní nápovědu. ->maxLength() a ->minLength() vykreslí atributy maxlength / minlength. Žádný z nich nepřidává Laravel pravidlo a žádný nepřežije request, který nepřišel z vašeho formuláře — serveru se musí zvlášť říct, co přijme:

Metoda Co doopravdy dělá Pravidlo, které dopsat
->email() type=email, inputmode=email ->rules(['email'])
->numeric() type=number, inputmode=decimal ->rules(['numeric'])
->integer() type=number, inputmode=numeric, step=1 ->rules(['integer'])
->url() type=url ->rules(['url'])
->tel() type=tel ->rules(['regex:…']), nebo použijte PhoneInput
->maxLength(255) maxlength="255" ->rules(['max:255'])
->minLength(3) minlength="3" ->rules(['min:3'])

Helpery, které pravidlem jsou: ->required() (a ->requiredWith()), který předřadí required, a ->unique(). Některá pole navíc nesou implicitní pravidla, která si přidají sama, protože jejich stav jinak zkontrolovat nejde: MoneyInput validuje částku za formátovaným textem, PhoneInput číslo za předvolbou, FileUpload nakonfigurované mime typy a velikosti a pole s options() omezení in: nad vlastními klíči voleb (pokud jste si žádné nedeklaroval).

Vyprázdněné číselné pole nepotřebuje pravidlo, aby bylo bezpečné. <input type=number> po vymazání odešle '' a TextInput z toho cestou k záznamu udělá null, místo aby do číselného sloupce zapsal prázdný řetězec. Viz Prázdné hodnoty.

Unikátní hodnoty

unique() sestaví laravelovské Rule::unique() z toho, co formulář už zná: tabulku z navázaného modelu, sloupec z názvu pole a — v režimu editace — vyloučí editovaný záznam z jeho vlastní kontroly.

TextInput::make('email')->unique(); // unique:users,email, ignoruje tohoto uživatele
TextInput::make('email')->unique(ignoreRecord: false); // počítá se každý řádek, včetně tohoto
TextInput::make('tax_id')->unique(column: 'vat_number'); // pole, jehož název není sloupec
TextInput::make('name')->unique(table: 'companies'); // formulář bez ->model()

Pravidlo vzniká až při validaci, ne při deklaraci schématu. To je podstatné, protože záznam předává formulářový runtime až poté, co vaše metoda form() skončila — pravidlo vyhodnocené při deklaraci by neignorovalo nic právě na tom formuláři, pro který bylo napsáno.

Kontrolu dále zúžíte přes modifyRuleUsing, které dostane pravidlo Unique:

TextInput::make('email')
->unique(modifyRuleUsing: fn (Unique $rule) => $rule->where('team_id', $this->teamId));

Formulář bez ->model() nemá z čeho tabulku odvodit, takže ji předejte: bez jednoho i druhého vyhodí unique() výjimku FormConfigurationException s názvem pole.

Vlastní validační zprávy

TextInput::make('name')
->required()
->validationMessages([
'required' => 'Please enter a name.',
'max' => 'Name is too long.',
]);

Pravidla na úrovni formuláře

Přidejte pravidla na úrovni formuláře, která zahrnují více polí:

Form::make()
->schema([
TextInput::make('password')->password()->required()->rules(['confirmed']),
TextInput::make('password_confirmation')->password()->required()->dehydrated(false),
])
->validationMessages([
'password.confirmed' => 'Passwords do not match.',
]);

Potvrzovací pole má pravidlo, ale žádný sloupec za sebou, proto je označené dehydrated(false): účastní se validace a před zápisem záznamu vypadne. Bez toho by uložení zkusilo nastavit na modelu atribut password_confirmation a selhalo na chybějícím sloupci — viz Životní cyklus uložení.


Programová validace

validate()

Zvaliduje stav proti všem posbíraným pravidlům a vrátí zvalidovaná data:

// V Livewire komponentě
public function save(): void
{
$data = $this->form->validate();
// $data obsahuje jen zvalidovaná pole
// Při selhání vyhodí Illuminate\Validation\ValidationException
}

getValidationRules()

Prohlédnout si posbíraná pravidla bez validace:

$rules = $this->form->getValidationRules();
// ['name' => ['required', 'string', 'max:255'], 'email' => ['required', 'email'], ...]

Validace v životním cyklu uložení

Při volání $form->save() proběhne validace automaticky jako první krok:

save()
├── 1. Validace ← všechna pravidla polí + formuláře
├── 2. mutateDataBeforeSave()
├── 3. Plugin hook: form.saving
├── 4. beforeSave()
├── 5. Perzistence (create/update)
├── 6. Uložení relací
├── 7. afterSave()
├── 8. Plugin hook: form.saved
└── 9. Úspěšná notifikace

Pokud validace selže, save() vyhodí ValidationException a kroky 2-9 se přeskočí.


Samostatná validace (bez Livewire)

$form = Form::make()
->schema([
TextInput::make('name')->required(),
TextInput::make('email')->email()->required(),
])
->state(['name' => '', 'email' => 'not-an-email']);
 
try {
$data = $form->validate();
} catch (ValidationException $e) {
$errors = $e->errors();
// ['name' => ['The name field is required.'], 'email' => ['The email field must be a valid email address.']]
}

Podmíněná pravidla

Pravidla mohou používat closury pro dynamickou validaci. Closura dostane reaktivní accessory $get / $set pole, takže pravidla mohou záviset na živém stavu sousedů. Closura může obalit celou sadu pravidel, nebo sedět uvnitř pole pravidel jako jedna položka:

TextInput::make('company_name')
->required(fn (callable $get) => $get('type') === 'business')
->rules(fn (callable $get) => $get('type') === 'business' ? ['min:2'] : []);
 
// Closury mohou být i jednotlivé položky v poli pravidel:
TextInput::make('slug')->rules([
'string',
fn (callable $get) => $get('type') === 'business' ? 'required' : 'nullable',
]);

Podmiňovací helpery

Fluent zkratky vyjadřují nejběžnější mezipolní podmínky bez psaní closury. Každá porovnává živou hodnotu jiného pole; předání pole odpovídá „je jedno z“.

Metoda Chování
->requiredIf('type', 'business') required, když se type rovná hodnotě (nebo je jednou z pole)
->requiredUnless('type', 'individual') required, pokud se type nerovná hodnotě
->requiredWith('company') required, když má company neprázdnou hodnotu
->visibleWhen('type', 'business') zobrazeno jen když type odpovídá
->hiddenWhen('type', 'individual') skryté když type odpovídá
->disabledWhen('locked', true) disabled když locked odpovídá
Select::make('department')
->visibleWhen('type', 'business')
->requiredIf('type', 'business');

visibleWhen / hiddenWhen / disabledWhen jsou sdílené foundation helpery, takže jsou dostupné i na sloupcích, filtrech a akcích. Na povrchu bez kontextu živého stavu jsou no-op (nechají komponentu viditelnou/zapnutou).

Skrytá pole se během validace přeskočí, takže pravidlo required na poli, které uživatel aktuálně nevidí, nikdy nezablokuje odeslání.


Live validace

Ve výchozím stavu formulář validuje jako celek při odeslání. Zapněte poli per-field validaci během reaktivního roundtripu, aby se jeho chyba objevila (a zmizela), jak uživatel interaguje, bez označení zbytku formuláře:

TextInput::make('email')->email()->required()->validateLive(); // při každé změně
TextInput::make('name')->required()->validateOnBlur(); // když focus odejde

validateLive() zapne live() a validateOnBlur() zapne live.blur vazbu, takže server vidí změnu a obnoví jen položku error bagu daného pole. Podmiňovací helpery jako requiredIf() se ctí i live, protože čtou aktuální stav sousedů při každém roundtripu. Live validace funguje i pro pole uvnitř Repeater položek — pole každého řádku validuje proti své vlastní item path (např. data.contacts.0.email).

Live validace kontroluje jedno pole po druhém. Pravidla, která porovnávají surové hodnoty sousedů přes řetězcovou syntax Laravelu (např. required_if:other,value), je nejlepší validovat při odeslání; pro reaktivní ekvivalent použijte requiredIf().


Zobrazení chyb

Validační chyby se automaticky navážou na Livewire error bag a zobrazí se vedle příslušných polí. Prefix state path se aplikuje automaticky:

// Když statePath('data') a pole je TextInput::make('name')
// Klíč chyby: data.name
// Livewire zobrazí: @error('data.name')

V Blade není potřeba žádné manuální vykreslování chyb.