Контролер чи замикання маршруту може повернути майже будь-що - Laravel сам перетворить результат на об'єкт Response:
| Що повертаємо | Що отримує клієнт |
|---|---|
| рядок | text/html з цим рядком |
| масив | JSON |
| модель Eloquent чи колекція | JSON (з урахуванням $hidden, $appends) |
view('posts.show', [...]) |
HTML з шаблону |
response(...) / response()->json(...) |
повний контроль: статус, заголовки, cookie |
redirect(...) |
відповідь 302 з заголовком Location |
| API Resource | JSON у форматі ресурсу |
об'єкт з інтерфейсом Responsable |
те, що поверне його toResponse() |
Route::get('/ping', fn () => 'pong');
Route::get('/settings', fn () => ['theme' => 'dark']);
Route::get('/users/{user}', fn (User $user) => $user);
return response('Created', 201)
->header('X-Request-Id', $requestId)
->cookie('seen_intro', '1', minutes: 60 * 24 * 30);
return response()->json(['message' => 'Accepted'], 202);
return response()->noContent(); // 204
Чому краще явні відповіді для API:
- модель напряму віддає всі її атрибути, крім
$hidden. Додали нову колонку в таблицю - вона автоматично з'явилася в API. API Resource описує формат явно; - статус-код: масив чи модель завжди повертають 200, а створення ресурсу - це 201, видалення - 204;
- заголовки (кешування, розташування нового ресурсу) задаються лише через об'єкт відповіді.
Відповідь має бути повернута: її треба саме повернути з контролера. Виклик response(...) без return нічого не робить. Щоб перервати виконання з будь-якого місця, використовують виняток: abort(404), throw ValidationException::withMessages(...) чи власний виняток з методом render().
Middleware бачить уже готову відповідь: після $next($request) можна додати заголовки чи cookie до будь-якої відповіді, незалежно від того, що повернув контролер.