Валидация в API
Отличия от web
В API валидация возвращает JSON с кодом 422, а не редирект. Формат:
{
"message": "The title field is required. (and 2 more errors)",
"errors": {
"title": ["The title field is required."],
"body": ["The body field is required."]
}
}
Form Request
Для API тоже используют Form Request:
php artisan make:request StorePostRequest
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StorePostRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'title' => 'required|string|max:255',
'body' => 'required|string|min:10',
'tags' => 'array',
'tags.*' => 'integer|exists:tags,id',
];
}
}
Использование
public function store(StorePostRequest $request)
{
$post = Post::create($request->validated());
return new PostResource($post);
}
Разные правила для store и update
public function rules(): array
{
$postId = $this->route('post')?->id;
return [
'title' => 'required|string|max:255|unique:posts,title,' . $postId,
'body' => 'required|string|min:10',
];
}
Сообщения
public function messages(): array
{
return [
'title.required' => 'Заголовок обязателен',
'body.min' => 'Текст слишком короткий',
];
}
Кастомный ответ на ошибку
protected function failedValidation(Validator $validator): void
{
throw new HttpResponseException(
response()->json([
'message' => 'Ошибка валидации',
'errors' => $validator->errors(),
], 422)
);
}
Условные правила
public function rules(): array
{
return [
'title' => 'required|string',
'published_at' => 'nullable|date',
'body' => Rule::requiredIf(fn () => $this->published_at !== null),
];
}