BAB 9: Responses
Mengirim berbagai jenis response: HTML, JSON, redirect, dan download file di Laravel.
Di bab sebelumnya kita membedah apa yang masuk ke aplikasi melalui objek Request. Sekarang saatnya melihat sisi yang lain: apa yang dikirim kembali ke browser atau klien API. Setiap method controller yang sudah kita tulis — dari index() yang mengembalikan view, hingga store() yang mengembalikan redirect — semuanya menghasilkan response. Bab ini membongkar semua jenis response yang tersedia di Laravel dan kapan masing-masing digunakan.
Jenis-jenis Response
Secara teknis, hampir semua yang kamu return dari controller atau route closure akan dikonversi oleh Laravel menjadi response HTTP. String menjadi response teks, array menjadi JSON, Eloquent model pun otomatis dikonversi ke JSON. Tapi untuk kontrol yang lebih detail, Laravel menyediakan helper response().
Response Teks Sederhana
// routes/web.php
// String — otomatis jadi response 200 dengan Content-Type text/html
Route::get('/ping', function () {
return 'pong';
});
// Array — otomatis jadi JSON dengan Content-Type application/json
Route::get('/status', function () {
return ['status' => 'ok', 'waktu' => now()->toIso8601String()];
});
Untuk mengontrol status code dan header secara eksplisit, gunakan helper response():
// routes/web.php
Route::get('/versi', function () {
return response('Laravel 12', 200)
->header('Content-Type', 'text/plain')
->header('X-Versi-Api', '1.0');
});
Method header() bisa di-chain sepanjang yang dibutuhkan. Jika perlu menetapkan banyak header sekaligus, gunakan withHeaders():
return response($konten)
->withHeaders([
'Content-Type' => 'text/plain',
'Cache-Control' => 'no-cache, no-store',
'X-Aplikasi' => 'Catatan App',
]);
Response JSON
Response JSON adalah pilihan utama untuk API. Gunakan response()->json() agar Laravel secara otomatis mengatur header Content-Type: application/json dan mengubah data ke format JSON:
<?php
// app/Http/Controllers/Api/CatatanController.php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\Catatan;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class CatatanController extends Controller
{
public function index(): JsonResponse
{
$catatan = Catatan::latest()->get();
return response()->json([
'data' => $catatan,
'total' => $catatan->count(),
]);
}
public function show(Catatan $catatan): JsonResponse
{
return response()->json([
'data' => $catatan,
]);
}
public function store(Request $request): JsonResponse
{
$catatan = Catatan::create($request->only(['judul', 'isi']));
// Status 201 Created untuk resource baru
return response()->json([
'pesan' => 'Catatan berhasil disimpan.',
'data' => $catatan,
], 201);
}
}
Eloquent model bisa langsung di-return tanpa dibungkus json() — hasilnya sama. Namun membungkusnya di dalam json() memberikan fleksibilitas untuk menambahkan metadata seperti total atau pesan.
Untuk membangun API dengan konsistensi tinggi, pertimbangkan menggunakan API Resources Laravel — sebuah layer transformasi antara model Eloquent dan response JSON. Ini memungkinkan kamu mengontrol persis field apa yang tampil di API tanpa mengubah model.
Redirect
Redirect adalah response yang menginstruksikan browser untuk mengunjungi URL lain. Laravel menyediakan beberapa cara untuk membuat redirect tergantung tujuannya.
Redirect ke URL dan Named Route
<?php
// app/Http/Controllers/CatatanController.php
namespace App\Http\Controllers;
use App\Models\Catatan;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
class CatatanController extends Controller
{
public function store(Request $request): RedirectResponse
{
$catatan = Catatan::create($request->only(['judul', 'isi']));
// Redirect ke named route dengan parameter
return redirect()->route('catatan.show', $catatan);
}
public function destroy(Catatan $catatan): RedirectResponse
{
$catatan->delete();
// Redirect ke named route tanpa parameter
return redirect()->route('catatan.index');
}
}
redirect()->route() lebih aman daripada hardcode URL karena mengikuti perubahan URL secara otomatis ketika nama route tidak berubah.
Redirect Kembali dengan Flash Data
Pola paling umum di aplikasi web adalah redirect kembali ke halaman sebelumnya setelah operasi — biasanya disertai pesan sukses atau error:
public function update(Request $request, Catatan $catatan): RedirectResponse
{
$catatan->update($request->only(['judul', 'isi', 'prioritas']));
// Redirect ke halaman sebelumnya dengan flash message
return redirect()->back()
->with('sukses', 'Catatan berhasil diperbarui.');
}
public function store(Request $request): RedirectResponse
{
// Jika ada error validasi manual
if (empty($request->judul)) {
return redirect()->back()
->withInput() // pertahankan nilai form
->withErrors(['judul' => 'Judul wajib diisi.']); // kirim error
}
Catatan::create($request->only(['judul', 'isi']));
return redirect()->route('catatan.index')
->with('sukses', 'Catatan berhasil ditambahkan.');
}
Di Blade template, tampilkan flash message dari session:
{{-- resources/views/catatan/index.blade.php --}}
@if (session('sukses'))
<div class="alert alert-success">
{{ session('sukses') }}
</div>
@endif
@if ($errors->any())
<ul class="alert alert-danger">
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
@endif
Redirect ke URL Eksternal
Gunakan redirect()->away() untuk redirect ke domain lain. Method ini tidak melakukan validasi atau encoding URL:
public function hubungi(): RedirectResponse
{
return redirect()->away('https://github.com/abdasis');
}
Response View
Ketika controller perlu mengembalikan HTML, gunakan helper view() secara langsung atau melalui response()->view() jika perlu mengatur status code atau header:
<?php
// app/Http/Controllers/CatatanController.php
namespace App\Http\Controllers;
use App\Models\Catatan;
use Illuminate\Http\Response;
use Illuminate\View\View;
class CatatanController extends Controller
{
public function index(): View
{
// Cara paling umum — return view langsung
return view('catatan.index', [
'catatanList' => Catatan::latest()->paginate(10),
]);
}
public function tidakDitemukan(): Response
{
// Perlu mengatur status code — gunakan response()->view()
return response()
->view('errors.catatan-kosong', [], 404);
}
}
Umumnya return view() sudah cukup. response()->view() hanya diperlukan ketika status code atau header perlu dikustomisasi.
Download dan Tampil File
Untuk mengunduh atau menampilkan file yang tersimpan di server, Laravel menyediakan dua method yang berbeda perilakunya di browser.
Download File
response()->download() menginstruksikan browser untuk mengunduh file, bukan membukanya:
<?php
// app/Http/Controllers/LampiranController.php
namespace App\Http\Controllers;
use App\Models\Catatan;
use Illuminate\Http\Response;
class LampiranController extends Controller
{
public function unduh(Catatan $catatan): Response
{
// Path file di server
$pathFile = storage_path('app/' . $catatan->path_lampiran);
// Nama file yang tampil di dialog download browser
$namaUnduhan = 'catatan-' . $catatan->id . '.pdf';
return response()->download($pathFile, $namaUnduhan);
}
}
Tampilkan File di Browser
response()->file() menginstruksikan browser untuk membuka file langsung — berguna untuk gambar, PDF, atau file teks yang ingin ditampilkan inline:
public function pratinjau(Catatan $catatan): Response
{
$pathFile = storage_path('app/' . $catatan->path_lampiran);
return response()->file($pathFile);
}
Pastikan file yang ingin diakses benar-benar ada sebelum memanggil download() atau file(). Jika file tidak ditemukan, Laravel akan melempar exception. Gunakan file_exists($pathFile) untuk mengeceknya terlebih dahulu.
Response Macro
Jika ada pola response yang berulang di banyak tempat, kamu bisa mendefinisikannya sekali sebagai macro. Ini berguna untuk memastikan format response API konsisten di seluruh aplikasi:
<?php
// app/Providers/AppServiceProvider.php
namespace App\Providers;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot(): void
{
// Format sukses yang konsisten untuk semua API endpoint
Response::macro('sukses', function (mixed $data, string $pesan = 'Berhasil', int $status = 200) {
return Response::json([
'sukses' => true,
'pesan' => $pesan,
'data' => $data,
], $status);
});
// Format error yang konsisten
Response::macro('gagal', function (string $pesan, int $status = 400) {
return Response::json([
'sukses' => false,
'pesan' => $pesan,
'data' => null,
], $status);
});
}
}
Setelah macro didefinisikan, gunakan seperti method biasa:
// Di controller mana saja
public function show(Catatan $catatan)
{
return response()->sukses($catatan, 'Catatan ditemukan.');
}
public function store(Request $request)
{
if (empty($request->judul)) {
return response()->gagal('Judul tidak boleh kosong.', 422);
}
$catatan = Catatan::create($request->only(['judul', 'isi']));
return response()->sukses($catatan, 'Catatan berhasil disimpan.', 201);
}
Macro adalah cara sederhana membangun layer respons yang konsisten tanpa harus membuat class tambahan.
Latihan
Coba kerjakan latihan berikut untuk memantapkan pemahaman tentang responses:
-
Response adaptif — Modifikasi
CatatanController@indexagar mengembalikan JSON jika request mengandung headerAccept: application/json, dan view HTML untuk request browser biasa. Gunakan$request->expectsJson()yang sudah kita pelajari di Bab 8. -
Macro response API — Definisikan dua macro
suksesdangagalseperti contoh di atas. Refactor methodstore()dandestroy()diCatatanControlleragar menggunakan macro ini ketika$request->expectsJson()bernilaitrue. -
Download laporan — Buat endpoint
GET /catatan/eksporyang menghasilkan file teks berisi semua judul catatan (satu per baris) menggunakanresponse()->streamDownload(). Nama file yang diunduh haruscatatan-{tanggal-hari-ini}.txt.
Penutup Bab
Response adalah kata akhir yang diucapkan aplikasi ke browser atau API client — formatnya menentukan apakah pengguna melihat halaman HTML, mendapat data JSON, diarahkan ke halaman lain, atau mengunduh sebuah file. Dengan memahami seluruh toolset response Laravel, kamu bisa memilih bentuk yang paling tepat untuk setiap situasi.
Kita sudah menyelesaikan layer HTTP secara penuh: routing menentukan ke mana request diarahkan, middleware memeriksa request sebelum masuk, controller memproses logika, request membawa data masuk, dan response membawa data keluar. Layer berikutnya adalah tampilan — bagaimana HTML yang dikirim ke browser dihasilkan. Sistem view Laravel yang akan kita bahas di Bab 10 adalah tempat logika presentasi tinggal, terpisah rapi dari logika controller yang baru saja kita kuasai.