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

Senior: питання на співбесіді з теми «Валідація»

Питання з реальних співбесід з відповідями: Laravel і PHP, бази даних, JavaScript і фронтенд, Git, Docker, API, безпека й архітектура. Тими самими темами, що й тести.

2 питання

Правило unique - це SELECT перед вставкою. Між перевіркою й записом інший запит встигає вставити той самий email.

Запит A: SELECT ... email = 'a@x.com'   -> немає
Запит B: SELECT ... email = 'a@x.com'   -> немає
Запит A: INSERT a@x.com                 -> ок
Запит B: INSERT a@x.com                 -> дубль

Що робити:

  1. Унікальний індекс у базі - єдина справжня гарантія. Валідація лишається для зрозумілого повідомлення в нормальному випадку.
  2. Обробити порушення індексу - Laravel кидає UniqueConstraintViolationException, його перетворюють на ту саму помилку валідації. Або createOrFirst(), який робить це сам.
try {
    $user = User::create($data);
} catch (UniqueConstraintViolationException) {
    throw ValidationException::withMessages(['email' => __('validation.unique', ['attribute' => 'email'])]);
}

Деталі правила, про які питають:

  • при оновленні виключають поточний запис: Rule::unique('users')->ignore($user->id); ignore() ніколи не беруть з даних запиту - лише з моделі, інакше клієнт підставить чужий ID;
  • withoutTrashed() не враховує м'яко видалені записи;
  • регістр: Ada@x.com і ada@x.com різні для unique, тож email нормалізують до нижнього регістру ще до валідації.

Докладніше в документації: Правило unique

Для API валідація - це контракт: клієнти парсять помилки програмно, тож формат і поведінка мають бути передбачуваними.

Що Laravel дає з коробки: якщо запит очікує JSON (Accept: application/json), замість перенаправлення повертається 422:

{
    "message": "The email field is required. (and 1 more error)",
    "errors": {
        "email": ["The email field is required."],
        "items.0.quantity": ["The items.0.quantity field must be at least 1."]
    }
}

Вкладені ключі сплющуються в «крапкову» нотацію.

Що варто налаштувати:

  • Невідомі поля. #[FailOnUnknownFields] на запиті форми (або глобально FormRequest::failOnUnknownFields()) відхиляє поля, яких немає в правилах. Помилки клієнта на кшталт emial стають помітними одразу, а не тихо ігноруються.
  • Стабільні повідомлення. Клієнти не мають залежати від тексту - лише від ключів полів і HTTP-коду. Якщо потрібні машинні коди помилок, їх додають власним форматом відповіді.
  • Межі вхідних даних: max для рядків і масивів, ліміт розміру тіла запиту на вебсервері.
  • Мова повідомлень за заголовком Accept-Language, якщо API багатомовний.

Тести: assertUnprocessable() і assertInvalid([...])/assertJsonValidationErrors() фіксують контракт, щоб зміна правил не зламала клієнтів непомітно.

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