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

Питання на співбесіді: HTTP та Request

Найпопулярніші питання з реальних Laravel/PHP співбесід для всіх рівнів

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-запити

Валідацію можна писати просто в контролері:

public function store(Request $request)
{
    $data = $request->validate([
        'title' => ['required', 'string', 'max:255'],
        'body' => ['required'],
    ]);
}

Для двох правил цього досить. Коли їх десяток, а та сама форма ще й редагується, контролер розпухає, а правила дублюються між store() і update().

Form Request виносить це в окремий клас:

php artisan make:request StorePostRequest
class StorePostRequest extends FormRequest
{
    public function authorize(): bool
    {
        return $this->user()->can('create', Post::class);
    }

    /**
     * @return array<string, list<string>>
     */
    public function rules(): array
    {
        return [
            'title' => ['required', 'string', 'max:255'],
            'body' => ['required', 'string'],
            'published_at' => ['nullable', 'date'],
        ];
    }

    public function messages(): array
    {
        return ['title.required' => 'Вкажіть заголовок вакансії.'];
    }
}

Використання - тип у сигнатурі:

public function store(StorePostRequest $request)
{
    // сюди виконання дійде лише з валідними даними
    $post = Post::create($request->validated());
}

Що це дає: валідація й перевірка прав відбуваються до входу в метод; контролер лишається про свою справу; правила лежать в одному місці й перевикористовуються; prepareForValidation() дозволяє нормалізувати вхід (обрізати пробіли, привести формат) до перевірки.

Деталь, яку часто пропускають: authorize(), що повертає false, дає 403 - тобто Form Request закриває і валідацію, і доступ.

Докладніше в документації: Валідація

Http - обгортка над Guzzle з розумними значеннями за замовчуванням, але саме за замовчуванням і ховаються проблеми.

Базовий виклик:

$response = Http::withToken($token)
    ->timeout(5)
    ->retry(3, 200)
    ->get('https://api.example/vacancies', ['page' => 1]);

if ($response->failed()) {
    // ...
}

$data = $response->json();

Чотири речі, без яких у прод виходити не варто:

1. Таймаут. За замовчуванням запит може висіти 30 секунд, тримаючи PHP-воркер. Чужий сервіс, що «підвис», кладе ваш застосунок, а не свій. timeout(5) і connectTimeout(2) обовʼязкові.

2. Повтори з паузою. retry(3, 200) рятує від разових збоїв, але повторювати можна лише ідемпотентні запити: повтор POST про створення платежу створить його двічі.

3. Обробка помилки. Http не кидає виняток на 4xx/5xx - повертає відповідь із failed() === true. Код, що одразу робить ->json()['id'], отримає null і піде далі, ніби все гаразд. Або перевіряйте явно, або ставте ->throw().

4. Ізоляція від збоїв. Виклик чужого API під час обробки запиту робить вашу доступність залежною від чужої. Такі виклики належать у чергу, а на повторювані збої добре лягає circuit breaker.

У тестах - Http::fake(), щоб мережі не було зовсім:

Http::fake(['api.example/*' => Http::response(['id' => 1], 200)]);
Http::assertSent(fn ($request) => $request->url() === 'https://api.example/vacancies');

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