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

Junior: питання на співбесіді з теми «Запити й відповіді»

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

3 питання

Через об'єкт Request, який Laravel автоматично впроваджує в метод контролера:

public function store(Request $request)
{
    $name = $request->input('name', 'default');
    $email = $request->string('email'); // типізовані хелпери
    $active = $request->boolean('active');
    $all = $request->only(['name', 'email']);
}

Динамічний доступ $request->name теж працює, але його уникають через можливі колізії з параметрами маршруту. Для файлів - $request->file('avatar'), для перевірки наявності - $request->has('key').

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

Дані запиту приходять з різних місць, і Laravel дає окремі методи для кожного.

input() - тіло запиту й рядок запиту разом:

$name = $request->input('name');
$city = $request->input('address.city');     // вкладене поле через крапку
$tags = $request->input('tags.*.name');      // усі значення з масиву
$page = $request->input('page', 1);          // значення за замовчуванням

Для форм (application/x-www-form-urlencoded, multipart/form-data) і JSON-тіла (application/json) працює однаково. Якщо поле є і в тілі, і в рядку запиту, перевагу має тіло.

query() - лише рядок запиту (?sort=name&page=2):

$sort = $request->query('sort', 'created_at');

Корисно, коли важливо, звідки прийшло значення: наприклад, параметр фільтра не повинен підмінятися полем у тілі POST-запиту.

json() - лише JSON-тіло:

$items = $request->json('items');

Параметри маршруту - частина URL, а не вхідні дані запиту:

Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) { ... });

$request->route('post');   // з будь-якого місця, наприклад у middleware

Їх отримують аргументами контролера (з прив'язкою до моделі), а не через input().

Інші джерела:

Метод Що повертає
$request->all() усі вхідні дані разом з файлами
$request->only(['name', 'email']) лише вказані поля
$request->except(['password']) усе, крім указаних
$request->header('X-Request-Id') заголовок
$request->cookie('theme') cookie (розшифрований)
$request->file('avatar') завантажений файл

Важливе правило: для збереження даних використовуйте не all() чи input(), а $request->validated() з Form Request - лише ті поля, які пройшли валідацію. Інакше клієнт може надіслати поля, яких ви не очікували.

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

Форма має відправляти файли як multipart/form-data:

<form method="POST" action="/profile/avatar" enctype="multipart/form-data">
    @csrf
    <input type="file" name="avatar">
</form>

Без enctype браузер відправить лише назву файлу.

Отримання файлу:

$file = $request->file('avatar');     // UploadedFile чи null
$request->hasFile('avatar');          // чи є файл у запиті
$file->isValid();                     // чи завантажився без помилок

Спершу - валідація:

$validated = $request->validate([
    'avatar' => ['required', 'image', 'mimes:jpg,png,webp', 'max:2048'],   // max у кілобайтах
    'documents.*' => ['file', 'mimes:pdf', 'max:10240'],
]);

Збереження:

$path = $request->file('avatar')->store('avatars', 's3');
// avatars/Xk9...q2.jpg - унікальна випадкова назва

$path = $request->file('avatar')->storeAs('avatars', "{$user->id}.webp", 'public');

store() сам генерує унікальну назву - це правильний варіант за замовчуванням. У базу зберігають шлях, а не сам файл.

Інформація про файл:

Метод Що повертає Чи можна довіряти
getClientOriginalName() назва з комп'ютера користувача ні - лише для відображення
getClientOriginalExtension() розширення з назви ні
extension() розширення за вмістом (MIME) так
getSize() розмір у байтах так
getMimeType() тип за вмістом так

Типові помилки:

  • зберігати файл під оригінальною назвою - перезапис чужих файлів, обхід шляху, shell.php;
  • перевіряти лише розширення з назви файлу;
  • забути про ліміти PHP: upload_max_filesize і post_max_size у php.ini (і client_max_body_size у Nginx). Якщо файл більший, запит приходить без файлу і без зрозумілої помилки валідації - виглядає, ніби поле порожнє;
  • завантажувати користувацькі файли в public/ поруч з кодом.

Множинне завантаження: <input type="file" name="photos[]" multiple> і $request->file('photos') повертає масив.

Докладніше в документації: Завантажені файли