Laravel: API і ресурси
20 питань · ~20 хв · Версія v3.0
Увійдіть, щоб продовжити
API-ресурси й умовні поля, пагінація й метадані, ресурси JSON:API з Laravel 13, коди статусів, токени Sanctum і версіонування - питання всіх рівнів, від junior до lead.
- За спробу
- 20
- У пулі
- 47
- Проходжень
- 0
- Середній бал
- -
- Пройшли на 70%+
- -
Питання для підготовки
13 питаньIdempotency (ідемпотентність) - багаторазове виконання операції дає той самий результат, що й однократне. Критично для платежів і повторів завдань у чергах (де доставка «at least once»).
Реалізація для API - idempotency key:
$key = $request->header('Idempotency-Key');
return Cache::lock("idem:$key")->block(5, function () use ($key) {
if ($cached = Cache::get("idem:result:$key")) {
return $cached; // повернути попередній результат
}
$result = $this->charge(); // виконати один раз
Cache::put("idem:result:$key", $result, now()->addDay());
return $result;
});
Для завдань: перевірка «вже оброблено» за унікальним ключем, ShouldBeUnique, або БД-обмеження, що відсікають дублі.
Версіонування дозволяє розвивати 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.
Ключ data. Ресурс, повернений з контролера, загортається в об'єкт з ключем data:
{ "data": { "id": 1, "name": "Olena" } }
Обгортка дає місце для метаданих поруч з даними і захищає від вразливості старих браузерів з JSON-масивом на верхньому рівні.
public static $wrap = 'user'; // власний ключ для цього ресурсу
JsonResource::withoutWrapping(); // вимкнути глобально (AppServiceProvider)
withoutWrapping() не діє на пагіновані відповіді: їм data потрібен, бо поруч ідуть links і meta.
Метадані верхнього рівня:
// у класі ресурсу - щоразу, коли ресурс є кореневим
public function with(Request $request): array
{
return ['meta' => ['api_version' => '2026-10']];
}
// разово, з контролера
return UserResource::make($user)->additional(['meta' => ['cached' => false]]);
with() додається лише для кореневого ресурсу, не для вкладених.
Колекції:
return UserResource::collection(User::paginate(20));
Пагінована колекція автоматично отримує links (first, last, prev, next) і meta (current_page, total...). Для простої колекції - лише data.
Власний клас колекції - коли самій колекції потрібна логіка:
final class UserCollection extends ResourceCollection
{
public function toArray(Request $request): array
{
return [
'data' => $this->collection,
'summary' => ['active' => $this->collection->where('active', true)->count()],
];
}
}
Керування HTTP-відповіддю:
return UserResource::make($user)
->response()
->setStatusCode(201)
->header('Location', route('users.show', $user));
Або в ресурсі - withResponse(Request $request, JsonResponse $response) для заголовків, що потрібні щоразу.
Типові помилки:
- подвійна обгортка:
toArray()повертає['data' => [...]]- отримаєтеdata.data; - ключі колекції: за замовчуванням вони перенумеровуються; щоб зберегти, -
public $preserveKeys = true; - формат для клієнтів - це контракт: вимкнення обгортки чи зміна
$wrapна робочому API ламає всіх клієнтів, тож такі рішення приймають до першого релізу.
- Ресурсна модель URL: іменники в множині (
/posts,/posts/{id}/comments), дія - через HTTP-метод, а не в URL. - Коректні статус-коди: 200/201/204, 422 (валідація), 401/403, 404, 429.
- API Resources для відповіді - щоб відв'язати JSON від схеми БД і контролювати формат.
- Версіонування (
/v1) із самого старту. - Пагінація, фільтрація, сортування через query-параметри; не віддавати все одразу.
- Consistent error format - єдина структура помилок (Laravel дає
{ "message": ..., "errors": {...} }для 422). - Автентифікація через Sanctum/Passport, rate limiting на маршрутах.
- Idempotency для небезпечних повторюваних операцій (платежі).
- Документація (OpenAPI/Scribe) і контрактні тести.
Це різні рівні автентифікації:
- Breeze - стартовий набір UI: реєстрація/вхід/скидання пароля на Blade+Livewire або React/Vue. Для швидкого старту.
- Fortify - headless-бекенд автентифікації (без UI): логіка реєстрації, 2FA, скидання пароля. Під ним працює Breeze/Jetstream.
- Sanctum - легка автентифікація для SPA (через cookie) та простих API-токенів. Дефолт для більшості API.
- Passport - повноцінний OAuth2-сервер: видача access/refresh токенів стороннім клієнтам. Обирають, коли потрібен саме OAuth2.
Правило: SPA чи мобільний застосунок → Sanctum; «увійти через наш сервіс» для третіх сторін → Passport.
Спершу почитати
Прочитати - ще не значить знати
20 питань, по одному на екран, ~20 хв. Після завершення - розбір кожної помилки з посиланням на питання.