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

Питання на співбесіді рівня Senior

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

41 питань

Telescope - інструмент дебагу/спостереження. Збирає й показує у дашборді: запити, винятки, SQL-запити (з часом і дублями), завдання черг, листи, нотифікації, кеш, події, HTTP-клієнт.

php artisan telescope:install
  • Незамінний для пошуку N+1 (бачиш усі запити сторінки), повільних місць, помилок у чергах.
  • Дані зберігаються в БД; у проді обмежують доступ через gate viewTelescope та вмикають sampling, бо обсяг записів великий.

На відміну від Horizon (керування чергами), Telescope - про діагностику всього застосунку. У продакшені часто доповнюють зовнішнім APM (Sentry, Datadog).

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

У кластері з кількох інстансів локальний лічильник не годиться - потрібен спільний стан у Redis. Фасад RateLimiter під капотом використовує атомарні операції Redis (INCR + EXPIRE), тож підрахунок точний між усіма серверами.

RateLimiter::attempt(
    key: 'send-sms:'.$user->id,
    maxAttempts: 5,
    callback: fn () => $this->sendSms(),
    decaySeconds: 60,
);

Для складніших схем - алгоритми sliding window чи token bucket на Lua-скриптах (атомарність на стороні Redis, без гонок). Ключове: лічильник і його TTL мають змінюватися атомарно, інакше за конкурентного доступу ліміт «протікає».

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

Circuit Breaker захищає від каскадних збоїв при зверненні до ненадійної залежності (зовнішнє API, що «лежить»). Якщо помилок забагато - «ланцюг розривається», і запити певний час відхиляються миттєво, не витрачаючи ресурси на марні спроби.

Стани:

  • Closed - усе працює, запити йдуть.
  • Open - поріг помилок перевищено; запити одразу падають (fail fast).
  • Half-Open - через таймаут пропускаються пробні запити; успіх → Closed, провал → знову Open.
// концептуально через Cache як лічильник збоїв
if (Cache::get('cb:payments') === 'open') {
    throw new ServiceUnavailableException;
}

У Laravel реалізують через лічильники в Redis/Cache або пакети-обгортки HTTP-клієнта. Часто поєднують із retry + backoff.

CI автоматично перевіряє кожен пуш, CD - автоматично доставляє код.

Типовий пайплайн (GitHub Actions / GitLab CI):

- composer install
- vendor/bin/pint --test # стиль
- vendor/bin/phpstan analyse # статичний аналіз
- php artisan test --parallel # тести
- npm ci && npm run build # ассети
# → деплой при успіху

Деплой: SSH-скрипт, Docker-образ у реєстрі + rolling update у Kubernetes, або сервіси на кшталт Forge/Envoyer. На етапі деплою - migrate --force, кешування конфіга/маршрутів, queue:restart. CI/CD дає швидкий зворотний зв'язок і знижує ризик людської помилки при релізі.

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

  • Stateful - сервер зберігає стан клієнта між запитами (наприклад, сесія у файлі/пам'яті конкретного інстансу). Тоді потрібна «липкість» (sticky sessions) або спільне сховище.
  • Stateless - сервер не зберігає стану; кожен запит самодостатній і містить усе потрібне (наприклад, JWT/токен з даними автентифікації).
Stateful:  сесія на сервері  → потрібен спільний Redis/sticky LB
Stateless: токен у запиті     → будь-який інстанс обробить запит

Stateless легше масштабувати горизонтально - інстанси взаємозамінні. У Laravel веб-частина зазвичай stateful (сесії в Redis), API - stateless (Sanctum-токени). Для масштабування цей стан виносять у спільні Redis/БД.

Sharding - горизонтальне розбиття даних між кількома незалежними БД (шардами) за ключем (tenant_id, user_id, geo). Дозволяє вийти за межі одного сервера.

shard 1: користувачі 1–1M
shard 2: користувачі 1M–2M
  • Shard key обирають так, щоб дані рівномірно розподілялись і більшість запитів влучали в один шард.
  • Складнощі: запити між шардами, унікальність ID (часто UUID/Snowflake), ребалансування при додаванні шарда, відсутність крос-шардових операцій JOIN і транзакцій.

У Laravel реалізують через множинні з'єднання й маршрутизацію за shard key. Sharding - крайній захід, коли вертикальне масштабування та репліки вже не справляються.

Версіонування дозволяє розвивати API, не ламаючи наявних клієнтів. Стратегії:

URI versioning (найпоширеніше) - версія в шляху:

Route::prefix('v1')->group(base_path('routes/api_v1.php'));
Route::prefix('v2')->group(base_path('routes/api_v2.php'));

Header/Media-type versioning - Accept: application/vnd.app.v2+json. Чистіші URL, але складніше тестувати.

Практики:

  • Окремі неймспейси контролерів і API Resources на версію (V1\PostResource, V2\PostResource).
  • Бізнес-логіку виносити в спільні Action/Service, щоб не дублювати між версіями.
  • Політика deprecation: підтримувати стару версію певний строк, повертати заголовки Deprecation/Sunset.

Докладніше в документації: API Resources (версіонування)

Deadlock - дві транзакції взаємно блокують одна одну, чекаючи на ресурси, які тримає інша. СУБД виявляє це й «вбиває» одну з транзакцій.

Запобігання:

  • Єдиний порядок доступу до таблиць/рядків у всіх транзакціях.
  • Тримати транзакції короткими, блокувати якомога пізніше.
  • Правильні рівні ізоляції (не завищувати без потреби).

Обробка в Laravel - автоматичний повтор:

DB::transaction(function () {
    // ...
}, attempts: 3); // повторити при deadlock

Діагностика: SHOW ENGINE INNODB STATUS (MySQL), логи БД, моніторинг частоти deadlock. Інколи допомагає optimistic locking замість тривалих блокувань.

Докладніше в документації: Песимістичні блокування

Serverless виконує код без керування серверами: провайдер (AWS Lambda) сам масштабує під навантаження й тарифікує за фактичні виклики.

Laravel Vapor - платформа для деплою Laravel на AWS Lambda + API Gateway, з керованими БД, чергами (SQS), кешем і CDN.

Особливості й обмеження:

  • Авто-масштабування до нуля й під пік; платиш лише за використання.
  • Cold start - затримка першого запиту після простою.
  • Файлова система ефемерна → файли лише в S3.
  • Обмеження часу виконання Lambda → довгі задачі в черги.
  • Stateless за дизайном (сесії/кеш у Redis/DynamoDB).

Альтернатива - контейнери (ECS/Kubernetes), коли потрібен повний контроль або стабільні довготривалі процеси.

WebSocket - постійне двостороннє з'єднання поверх одного TCP, що дає реальний час без поллінгу.

У Laravel сервер WebSockets - Reverb (офіційний), Soketi або Pusher; події транслюються через Broadcasting, клієнт слухає через Echo.

Масштабування: коли інстансів WebSocket-сервера кілька, клієнти на різних інстансах не «бачать» одне одного. Рішення - Redis Pub/Sub як спільна шина: інстанс публікує повідомлення в Redis, усі інстанси отримують і розсилають своїм підключеним клієнтам.

client A ─ inst 1 ┐
                  ├─ Redis Pub/Sub ─┤
client B ─ inst 2 ┘

Окрема увага: авторизація private/presence-каналів, ліміти відкритих з'єднань, sticky sessions на балансувальнику.

Докладніше в документації: Broadcasting / WebSockets

2FA вимагає двох факторів: «що знаю» (пароль) + «що маю» (код із застосунку/SMS). Найпоширеніше - TOTP (Time-based One-Time Password) сумісно з Google Authenticator.

У Laravel найпростіше через Fortify, який має 2FA з коробки:

  • генерація секрету й QR-коду для прив'язки;
  • перевірка 6-значного коду при вході;
  • одноразові recovery codes на випадок втрати пристрою.
// Fortify вмикає features:
Features::twoFactorAuthentication(['confirm' => true]),

Під капотом - пакет pragmarx/google2fa. Важливо: зберігати секрет зашифрованим, давати recovery-коди, за бажанням «запам'ятати пристрій».

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

Laravel Scout - драйверна абстракція повнотекстового пошуку. Додаєте трейт до моделі - і вона автоматично синхронізується з пошуковим індексом (Meilisearch, Algolia, Elasticsearch, навіть database).

class Post extends Model
{
    use Searchable;

    public function toSearchableArray(): array
    {
        return ['title' => $this->title, 'body' => $this->body];
    }
}

Post::search('laravel queues')->paginate(15);
  • Індекс оновлюється на події моделі (краще - через чергу).
  • Початкове наповнення: php artisan scout:import "App\Models\Post".
  • Meilisearch дає швидкий typo-tolerant пошук «з коробки»; Elasticsearch - складніші аналітичні запити.

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

Value Object - невеликий незмінний (immutable) об'єкт, що представляє концепцію домену й порівнюється за значенням, а не за ідентичністю (на відміну від Entity з id).

final class Money
{
    public function __construct(
        public readonly int $cents,
        public readonly string $currency,
    ) {}

    public function add(Money $other): self
    {
        return new self($this->cents + $other->cents, $this->currency);
    }
}

Переваги: інкапсуляція правил (валюта, валідація email), самодокументований код, безпека (незмінність). У Laravel VO зручно зберігати через Custom Casts, перетворюючи між колонкою БД та об'єктом.

CSP - HTTP-заголовок, що визначає, з яких джерел дозволено завантажувати ресурси (скрипти, стилі, зображення). Це потужний захист від XSS: навіть якщо зловмисник впровадить <script>, браузер не виконає його, якщо джерело не дозволене.

Content-Security-Policy: default-src 'self';
    script-src 'self' https://cdn.example.com;
    img-src 'self' data:;

У Laravel заголовок додають через middleware (вручну або пакетом на кшталт spatie/laravel-csp).

Практики:

  • Уникати 'unsafe-inline' - використовувати nonce для інлайн-скриптів.
  • Спершу режим report-only (Content-Security-Policy-Report-Only) зі збором звітів, щоб не зламати сайт.

BDD розширює TDD, зміщуючи фокус на поведінку системи з погляду бізнесу/користувача, а не на технічні деталі. Сценарії описують зрозумілою мовою (Gherkin: Given-When-Then).

Scenario: Успішний вхід
  Given користувач зареєстрований
  When він вводить правильні дані
  Then він потрапляє на дашборд

У PHP-екосистемі - Behat. Pest також заохочує «describe behavior» стиль:

it('redirects to dashboard after login', function () {
    // ...
});

Цінність BDD - спільна мова між розробниками, QA та бізнесом; тести стають живою документацією очікуваної поведінки.