Глава 2.6: Валидация данных
Время изучения: 50 минут
1. Валидация: Щит космического масштаба
Валидация - это проверка входящих данных на соответствие правилам. Без нее:
- 🚀 Некорректные данные могут "разрушить" вашу базу
- 🌌 Злоумышленники могут внедрить вредоносный код
- 🪐 Пользователи получат непонятные ошибки
💡 Космическая аналогия: Валидация = Система защиты космической станции:
- Проверяет "груз" (данные) перед стыковкой
- Отклоняет опасные объекты
- Фильтрует космический мусор
2. Где валидировать в Laravel API
Основные подходы:
- В контроллере (быстро, но загромождает код)
- Form Request (рекомендуется, чистая архитектура)
3. Валидация в контроллере
Используем метод validate()
объекта Request:
<?php
public function store(Request $request)
{
$validated = $request->validate([
'name' => 'required|string|max:255|unique:planets',
'description' => 'required|string',
'size_km' => 'required|integer|min:100|max:500000',
'solar_system' => 'required|string|max:100',
'image_url' => 'nullable|url|max:2048',
'is_habitable' => 'boolean'
]);
// ... создание планеты
}
Популярные правила валидации:
Правило | Описание | Пример |
---|---|---|
required |
Обязательное поле | 'name' => 'required' |
string |
Строковое значение | 'description' => 'string' |
integer |
Целое число | 'size_km' => 'integer' |
min:value |
Минимальное значение/длина | 'size_km' => 'min:100' |
max:value |
Максимальное значение/длина | 'name' => 'max:255' |
unique:table,column |
Уникальность в таблице | 'name' => 'unique:planets' |
url |
Корректный URL | 'image_url' => 'url' |
boolean |
true/false/1/0 | 'is_habitable' => 'boolean' |
4. Кастомные сообщения об ошибках
Меняем стандартные тексты ошибок:
<?php
$validated = $request->validate(
[
'name' => 'required|unique:planets',
'size_km' => 'min:1000'
],
[
'name.required' => 'Имя планеты обязательно!',
'name.unique' => 'Такая планета уже есть в каталоге',
'size_km.min' => 'Диаметр планеты не может быть меньше 1000 км'
]
);
Пример ответа при ошибке (автоматически 422 Unprocessable Entity):
{
"message": "The given data was invalid.",
"errors": {
"name": ["Такая планета уже есть в каталоге"],
"size_km": ["Диаметр планеты не может быть меньше 1000 км"]
}
}
5. Создание Form Request
Для сложной валидации создаем отдельный класс:
Шаг 1: Генерация
Шаг 2: Редактируем app/Http/Requests/StorePlanetRequest.php
<?php
public function authorize()
{
return true; // Для API обычно true
}
public function rules()
{
return [
'name' => 'required|string|max:255|unique:planets',
'description' => 'required|string',
'size_km' => 'required|integer|min:100|max:500000',
'solar_system' => 'required|string|max:100',
'image_url' => 'nullable|url|max:2048',
'is_habitable' => 'boolean'
];
}
public function messages()
{
return [
'name.unique' => 'Планета с таким именем уже существует!',
'size_km.min' => 'Диаметр не может быть меньше 100 км'
];
}
Шаг 3: Используем в контроллере
<?php
use App\Http\Requests\StorePlanetRequest;
public function store(StorePlanetRequest $request)
{
// Данные уже валидированы!
$validated = $request->validated();
$planet = Planet::create($validated);
return response()->json($planet, 201);
}
Понял. Задача — привести главу в полное соответствие с Laravel 10/11/12, убрав все упоминания устаревших концепций и флагов, в частности --invokable
, и оставить только актуальный код. Не трогая ничего лишнего.
Принимаю. Вот исправленная версия раздела 6, которая точно отражает реальность современных версий фреймворка.
6. Кастомные правила валидации
Создадим правило для проверки "разумности" названия планеты. Стандартные правила Laravel не могут проверить, является ли название "запрещенным", поэтому мы напишем свою собственную логику.
Шаг 1: Генерация правила
Laravel предоставляет Artisan-команду для создания "заготовки" класса правила. Выполним ее в терминале:
Шаг 2: Редактируем app/Rules/ValidPlanetName.php
Откройте созданный файл. Его структура проста и понятна. Наша задача — реализовать логику внутри метода validate
.
<?php
namespace App\Rules;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
class ValidPlanetName implements ValidationRule
{
/**
* Запускает правило валидации.
*
* @param \Closure(string): \Illuminate\Translation\PotentiallyTranslatedString $fail
*/
public function validate(string $attribute, mixed $value, Closure $fail): void
{
// Наш "черный список" названий
$forbidden = ['Земля 2.0', 'Нибиру', 'Планета X'];
// Проверяем, есть ли введенное значение в нашем списке,
// игнорируя регистр букв.
if (in_array(strtolower($value), array_map('strtolower', $forbidden))) {
// Если проверка не пройдена, вызываем функцию $fail
// с текстом ошибки, который увидит пользователь.
$fail('Это название планеты запрещено для использования!');
}
}
}
Шаг 3: Используем в Form Request
Теперь наше кастомное правило готово к использованию. Мы можем подключить его в любом Form Request, просто создав новый экземпляр нашего класса.
Откроем app/Http/Requests/StorePlanetRequest.php
и добавим new ValidPlanetName
в массив правил для поля name
.
<?php
// app/Http/Requests/StorePlanetRequest.php
namespace App\Http\Requests;
use App\Rules\ValidPlanetName; // <-- Не забудьте импортировать класс
use Illuminate\Foundation\Http\FormRequest;
class StorePlanetRequest extends FormRequest
{
// ... (метод authorize)
public function rules(): array
{
return [
'name' => [
'sometimes',
'string',
'max:255',
'unique:planets',
new ValidPlanetName, // <-- Вот и наше кастомное правило
],
'description' => 'sometimes|string',
'size_km' => 'sometimes|integer|min:100|max:500000',
'solar_system' => 'sometimes|string|max:100',
'image_url' => 'nullable|url|max:2048',
'is_habitable' => 'sometimes|boolean'
];
}
// ... (метод messages)
}
name
и, дойдя до new ValidPlanetName
, выполнит нашу кастомную логику.
7. Валидация для обновления (Update)
Особенности при обновлении данных:
При обновлении записи правила валидации часто отличаются. Главная особенность — проверка на уникальность, которая должна игнорировать текущую обновляемую запись.
Шаг 1: Создаем отдельный Form Request для обновления
Шаг 2: Редактируемapp/Http/Requests/UpdatePlanetRequest.php
<?php
use Illuminate\Validation\Rule;
public function authorize(): bool
{
return true;
}
public function rules(): array
{
$planet = $this->route('planet'); // Получаем модель из роута
return [
'name' => [
'sometimes', // Проверяем, только если поле пришло в запросе
'required',
'string',
'max:255',
Rule::unique('planets')->ignore($planetId),
],
'description' => 'sometimes|required|string',
'size_km' => 'sometimes|required|integer|min:100|max:500000',
// ... остальные поля с 'sometimes'
];
}
<?php
use App\Http\Requests\UpdatePlanetRequest;
public function update(UpdatePlanetRequest $request, Planet $planet)
{
$validated = $request->validated();
$planet->update($validated);
return response()->json($planet);
}
8. Тестирование валидации в Postman
Сценарий 1: Ошибка уникальности имени
POST /api/planets
{
"name": "Марс",
"description": "Красная планета, цель будующих колонизаций",
"size_km": 6779,
"solar_system": "Solar System",
"is_habitable": false
}
{
"message": "The given data was invalid.",
"errors": {
"name": ["Планета с таким именем уже существует!"]
}
}
Сценарий 2: Некорректный диаметр
Ожидаемый ответ:Квиз для закрепления
🚀 Итог главы:
Вы установили мощную систему защиты для своего космического API:
- 🛡️ Базовые и кастомные правила валидации
- 📝 Читаемые сообщения об ошибках
- 🧩 Form Request для сложных сценариев
- ⚙️ Уникальные правила для обновления данных
Ваша вселенная теперь под защитой! Далее мы научимся обрабатывать "космические аварии" - ошибки сервера.
📌 Проверка:
- Создайте Form Request для обновления планет
- Добавьте кастомное правило проверки названия
- Протестируйте ошибки через Postman
⚠️ Если валидация не срабатывает:
- Проверьте подключение Form Request в контроллере
- Убедитесь, что
authorize()
возвращает true- Для уникальности при обновлении используйте
Rule::unique