Publikováno
· Autor: Zdeněk Hejzlar · Pod kapotou · Základy · 3 min čtení
Obsah článku
Máte v controlleru dvacet řádků kontrol, které se opakují u každé akce, a ten soubor už se nedá číst? Tohle je klasika, kterou jsem sám dlouho dělal špatně. Laravel na to má čisté řešení — Form Request, kam validaci přesunete celou.
Proč nevalidovat v controlleru
Validace přímo v metodě controlleru funguje, ale rychle bobtná a míchá dvě zodpovědnosti dohromady — kontrolu vstupu a samotnou logiku. Form Request je samostatná třída, která:
- drží pravidla i chybové hlášky na jednom místě;
- jde znovu použít u více akcí;
- odlehčí controlleru, takže je konečně čitelný.
Vytvoření Form Requestu
Vygenerujete ho Artisanem a vyplníte dvě metody — authorize() řeší oprávnění, rules() samotná pravidla:
php artisan make:request UlozClanekRequest
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'nazev' => ['required', 'string', 'max:160'],
'obsah' => ['required', 'string'],
'email' => ['required', 'email'],
];
}
V controlleru pak jen napíšete tenhle request jako typ parametru. Validace proběhne automaticky ještě před tělem metody — když neprojde, uživatel se vrátí na formulář s chybami:
public function store(UlozClanekRequest $request): RedirectResponse
{
$clanek = Clanek::create($request->validated());
return redirect()->route('clanky.show', $clanek);
}
Metoda validated() vrátí jen data, která prošla pravidly. To je důležité — nikdy tak do databáze neuložíte nic, co jste nečekali. Kdybyste místo toho použili celý vstup z prohlížeče, riskujete, že si někdo přes upravený formulář nastaví pole, které jste mu nechtěli dát. Přesně tomuhle se říká mass assignment a Form Request vás před ním chrání.
Pravidla zapisuji nejraději polem, ne řetězcem odděleným svislítky. Je to o něco upovídanější, zato se do pole snadno přidá vlastní pravidlo jako objekt a nemusíte hlídat kolize se speciálními znaky. Zvolte jeden styl a držte se ho v celém projektu.
Vlastní hlášky
Výchozí hlášky jsou anglické a obecné. Přepíšete je metodou messages(), ať uživatel dostane srozumitelnou zpětnou vazbu v češtině:
public function messages(): array
{
return [
'nazev.required' => 'Vyplňte prosím název.',
'email.email' => 'Zadejte platnou e-mailovou adresu.',
];
}
Stojí za to zmínit i metodu authorize(). Právě tady rozhodnete, jestli má přihlášený uživatel na akci vůbec právo — třeba že článek smí upravit jen jeho autor. Když vrátí false, Laravel požadavek odmítne dřív, než se cokoli stane. Validace vstupu a kontrola oprávnění tak sedí pohromadě na jednom místě, což se mi osvědčilo mnohem víc než rozházet je po controlleru.
Za zmínku stojí, že validace není jen o pohodlí — je to první linie bezpečnosti. Když vstup poctivě kontrolujete, výrazně ztěžujete útočníkům práci a uzavíráte řadu běžných děr. Nikdy nevěřte tomu, co přijde z prohlížeče.
Kdy stačí jednodušší cesta
Buďme upřímní: u jediného formuláře s dvěma poli je samostatná třída trochu overkill a klidně zvaliduju přímo v controlleru přes $request->validate(). Jakmile ale pravidla přibývají nebo je sdílíte, Form Request se vyplatí. Je to o míře, ne o dogmatu.
Ve PHP a Laravelu je validace vstupu základ každé rozumné akce. Když už formuláře stavíte v administraci, mrkněte na Filament resource od nuly — tam se validace řeší podobně, jen deklarativně u jednotlivých polí.
Chcete mít formuláře na webu poctivě ošetřené? Napište mi, nezávazně to probereme.