Валидация — одна из тех «мелочей», которые могут постепенно разрушить кодовую базу. Поначалу это просто пара вызовов request()->validate() внутри ваших контроллеров, но по мере добавления новых полей и эндпоинтов вы получаете дублирующиеся массивы валидации и контроллеры, переполненные условными операторами.
Laravel Form Requests решают эту проблему, вынося логику валидации и авторизации в отдельные классы.
Сначала это пара вызовов request()->validate() внутри контроллеров.
Затем вы добавляете больше полей, больше эндпоинтов, больше правил… и внезапно у вас появляются:
- дублирующиеся массивы валидации,
- контроллеры, забитые условными операторами,
- несогласованные сообщения об ошибках,
- и проверки в духе «кому разрешено это делать?», перемешанные с логикой валидации.
Философия: Контроллеры оркеструют, Form Requests валидируют
Form Request — это кастомный класс, который централизует:
- rules(): вашу логику валидации.
- authorize(): проверку того, кому разрешено выполнять действие.
- messages(): кастомные сообщения об ошибках.
- prepareForValidation(): нормализацию данных перед применением правил.
Коротко говоря:
Контроллеры оркеструют. Form Requests валидируют (и могут авторизовать).
Зачем использовать Form Requests?
1) Сохраняйте контроллеры чистыми
Контроллеры остаются сосредоточенными на том, что делать, а не на том, как валидировать.
2) Безопасное повторное использование правил
StorePostRequest и UpdatePostRequest могут переиспользовать или расширять правила без копипаста.
3) Централизация авторизации для действия
Метод authorize() может отлично дополнять Policies:
- Policy определяет права доступа к ресурсу
- Form Request определяет право на выполнение действия (например, «можно ли создать?»)
4) Упрощение тестирования
Form Requests позволяют легко и просто тестировать валидацию и граничные случаи.
Создание Form Request
php artisan make:request StoreProjectRequest
Вы получите что-то вроде:
// app/Http/Requests/StoreProjectRequest.php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreProjectRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [];
}
}
Базовый пример: сохранение Project
Form Request
// app/Http/Requests/StoreProjectRequest.php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class StoreProjectRequest extends FormRequest
{
public function authorize(): bool
{
// Option A: keep it simple
return auth()->check();
// Option B: delegate to a Policy (recommended in many apps)
// return $this->user()->can('create', Project::class);
}
public function rules(): array
{
return [
'name' => ['required', 'string', 'min:3', 'max:120'],
'description' => ['nullable', 'string', 'max:2000'],
'status' => ['required', Rule::in(['draft', 'active'])],
'starts_at' => ['nullable', 'date'],
];
}
}
Контроллер остается компактным
// app/Http/Controllers/ProjectController.php
use App\Http\Requests\StoreProjectRequest;
class ProjectController
{
public function store(StoreProjectRequest $request)
{
$data = $request->validated();
// ... create logic (model/service/use case)
// Project::create([...$data, 'user_id' => $request->user()->id]);
return redirect()->back()->with('status', 'Project created!');
}
}
Обратите внимание на главные преимущества:
- валидация вынесена из контроллера
-
$request->validated()гарантирует, что пройдут только проверенные поля
Улучшение сообщений об ошибках (опционально)
public function messages(): array
{
return [
'name.required' => 'Please provide a project name.',
'name.min' => 'Project name must be at least :min characters.',
];
}
public function attributes(): array
{
return [
'starts_at' => 'start date',
];
}
Нормализация входных данных с помощью prepareForValidation()
Очень полезно для очистки данных до того, как сработают правила валидации.
protected function prepareForValidation(): void
{
$this->merge([
'name' => trim((string) $this->input('name')),
]);
}
Частые сценарии использования:
- обрезка пробелов у строк (trim),
- приведение «on» к булевому значению,
- маппинг устаревших ключей (legacy keys),
- установка значений по умолчанию для отсутствующих полей.
Продвинутый паттерн: общие правила для Store/Update
Часто ваши правила обновления слегка отличаются (например, ограничения уникальности).
// app/Http/Requests/UpdateProjectRequest.php
use Illuminate\Validation\Rule;
public function rules(): array
{
$projectId = $this->route('project')?->id;
return [
'name' => [
'required', 'string', 'max:120',
Rule::unique('projects', 'name')->ignore($projectId),
],
'status' => ['required', Rule::in(['draft', 'active', 'archived'])],
];
}
Как Form Requests сочетаются с Policies
Чистая архитектура выглядит так:
- Policy → права доступа на уровне ресурса («можно ли обновить ЭТОТ проект?»)
- Form Request → валидация входных данных (+ опциональные проверки на уровне действия)
Пример:
- Контроллер вызывает
$this->authorize('update', $project)(Policy) - Form Request валидирует поля и формирует структуру входных данных
Такое разделение делает логику авторизации явной и пригодной для повторного использования.
Быстрое тестирование валидации
Даже несколько тестов помогут предотвратить регрессии.
public function test_project_name_is_required(): void
{
$response = $this->post('/projects', [
'name' => '',
'status' => 'draft',
]);
$response->assertSessionHasErrors(['name']);
}
Чек-лист для сохранения
- [ ] Создавайте Form Request для каждого действия (
StoreXRequest,UpdateXRequest) - [ ] Делайте контроллеры тонкими:
$request->validated() - [ ] Нормализуйте входные данные в
prepareForValidation()при необходимости - [ ] Используйте Policies для проверки прав на ресурсы; опционально вызывайте их в
authorize() - [ ] Добавляйте 3–5 тестов для критически важных правил валидации
Итог
Laravel Form Requests — это простая привычка, которая сохраняет проект чистым по мере его роста:
- контроллеры остаются читаемыми,
- правила валидации остаются согласованными,
- авторизация становится более понятной,
- а рефакторинг — более безопасным.
Комментарии (0)
Пока нет комментариев — будьте первым.