Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як типізовано показати помилки валідації Laravel (422) у формі на фронтенді?

Laravel на помилку валідації для запиту з Accept: application/json повертає 422 з тілом:

{
  "message": "The email field must be a valid email address. (and 1 more error)",
  "errors": {
    "email": ["The email field must be a valid email address."],
    "items.0.qty": ["The items.0.qty field must be at least 1."]
  }
}

Типізований розбір на клієнті:

import * as z from 'zod';

const LaravelValidationError = z.object({
  message: z.string(),
  errors: z.record(z.string(), z.array(z.string())),
});

export class ValidationError<F extends string = string> extends Error {
  constructor(public readonly errors: Partial<Record<F, string[]>>) {
    super('Validation failed');
    this.name = 'ValidationError';
  }
}

if (response.status === 422) {
  const body = LaravelValidationError.parse(await response.json());
  throw new ValidationError(body.errors);
}

Прив'язка до полів форми. Ключі помилок мають відповідати полям - це можна перевірити типами:

type OrderForm = { email: string; items: { qty: number }[] };
type FieldPath = 'email' | `items.${number}.qty`;

function firstError(errors: Partial<Record<FieldPath, string[]>>, field: FieldPath) {
  return errors[field]?.[0];
}

Шаблонний рядковий тип `items.${number}.qty` описує вкладені ключі масивів так само, як їх формує Laravel.

Одна схема для клієнтської й серверної помилки. Якщо форма перевіряється Zod на клієнті, помилки Zod варто привести до того самого формату, що й у Laravel:

const result = OrderFormSchema.safeParse(values);
if (!result.success) {
  const { fieldErrors } = z.flattenError(result.error);   // { email: ['...'], ... }
}

Тоді компонент форми показує помилки однаково, незалежно від того, звідки вони прийшли.

Що варто врахувати:

  • клієнтська перевірка - для зручності, серверна - для захисту. Сервер перевіряє завжди, і його помилки мають показуватися навіть тоді, коли клієнтська схема їх «пропустила» (наприклад, унікальність email);
  • ключі вкладених полів: у Laravel items.0.qty, у бібліотеках форм - часто items[0].qty. Потрібне перетворення в одному місці;
  • мова повідомлень: Laravel повертає їх мовою застосунку (lang/uk/validation.php), клієнтські повідомлення Zod теж треба локалізувати (z.config() з українською локаллю чи власні повідомлення);
  • Inertia працює інакше: помилки валідації приходять не відповіддю 422, а як props errors після редиректу, і useForm розкладає їх за полями сам.

Докладніше в документації: Zod: форматування помилок

Схожі питання