Routing
Rute adalah kontrak publik aplikasimu. Laravel membuatnya deklaratif, dan route model binding membuat sebagian besar controller berhenti menulis query pencarian.
Intisari
routes/web.phppunya session dan CSRF.routes/api.phpstateless โ dibuat olehphp artisan install:apidengan prefiks/apiotomatis.- Beri nama setiap rute.
route('produk.show', $p)tidak akan patah saat URL-nya berubah. - Route model binding: ketik parameter dengan model, dan Laravel yang mencarikan โ 404 otomatis kalau tidak ada.
- Urutan penting: rute yang lebih spesifik harus didaftarkan sebelum yang punya parameter.
php artisan route:listadalah jawaban pertama untuk hampir semua 404 dan 405.
Bentuk dasar
use App\Http\Controllers\ProdukController;
Route::get('/produk', [ProdukController::class, 'index'])->name('produk.index');
Route::get('/produk/{produk}', [ProdukController::class, 'show'])->name('produk.show');
Route::post('/produk', [ProdukController::class, 'store'])->name('produk.store');
// Tujuh rute CRUD sekaligus, dengan nama yang sudah konsisten
Route::resource('produk', ProdukController::class);
// Untuk API: tanpa create dan edit (dua rute yang menampilkan form)
Route::apiResource('produk', ProdukController::class);
| Method | URI | Aksi | Nama |
|---|---|---|---|
| GET | /produk | index | produk.index |
| GET | /produk/create | create | produk.create |
| POST | /produk | store | produk.store |
| GET | /produk/{produk} | show | produk.show |
| GET | /produk/{produk}/edit | edit | produk.edit |
| PUT/PATCH | /produk/{produk} | update | produk.update |
| DELETE | /produk/{produk} | destroy | produk.destroy |
Route model binding โ fitur yang paling menghemat kode
// Tanpa binding
Route::get('/produk/{id}', function (int $id) {
$produk = Produk::findOrFail($id);
return view('produk.show', compact('produk'));
});
// Dengan binding โ nama parameter harus sama dengan nama variabel bertipe
Route::get('/produk/{produk}', function (Produk $produk) {
return view('produk.show', compact('produk'));
});
Laravel mencari Produk berdasarkan primary key dan otomatis mengembalikan 404 kalau
tidak ketemu. Untuk mencari lewat kolom lain, sebutkan kolomnya:
Route::get('/produk/{produk:slug}', [ProdukController::class, 'show']);
// Binding bersarang: memastikan ulasan ini benar-benar milik produk itu
Route::get('/produk/{produk}/ulasan/{ulasan}', ...)->scopeBindings();
scopeBindings() itu soal keamanan, bukan kerapian. Tanpa itu, ulasan dicari
di seluruh tabel โ jadi /produk/7/ulasan/999 bisa menampilkan ulasan milik produk lain. Dengan
scopeBindings(), pencariannya dibatasi ke relasi milik produk 7 saja. Kelas bug ini โ
insecure direct object reference โ adalah temuan audit keamanan yang sangat umum.
Grup: menulis sekali untuk banyak rute
Route::middleware(['auth', 'verified'])
->prefix('admin')
->name('admin.')
->group(function () {
Route::get('/dasbor', [DasborController::class, 'index'])->name('dasbor');
// nama akhirnya: admin.dasbor, URI: /admin/dasbor
Route::resource('pengguna', PenggunaController::class);
});
Urutan pendaftaran menentukan hasil
// SALAH โ "/produk/populer" akan ditangkap oleh rute parameter di atasnya
Route::get('/produk/{produk}', ...);
Route::get('/produk/populer', ...); // tidak akan pernah tercapai
// BENAR โ yang literal duluan
Route::get('/produk/populer', ...);
Route::get('/produk/{produk}', ...);
Router memeriksa rute dari atas ke bawah dan berhenti di kecocokan pertama. Gejalanya khas: kamu mendapat 404
"Produk tidak ditemukan" padahal yang kamu minta bukan produk โ melainkan kata populer yang
diperlakukan sebagai ID.
web.php versus api.php
routes/web.php | routes/api.php | |
|---|---|---|
| Session & cookie | Ya | Tidak (stateless) |
| Perlindungan CSRF | Ya | Tidak โ token yang menggantikannya |
| Prefiks URI | Tidak ada | /api otomatis |
| Respons saat gagal validasi | Redirect balik + error di session | JSON 422 |
| Cara mengaktifkan | Sudah ada | php artisan install:api |
install:api sekalian memasang Sanctum โ guard token untuk SPA, aplikasi mobile, dan
konsumen pihak ketiga. Kita bahas di Fase 4. Untuk sekarang cukup tahu: memilih file rute berarti memilih
seperangkat middleware, dan itulah perbedaan sesungguhnya antara keduanya.
Alat diagnostik
php artisan route:list
php artisan route:list --path=produk # saring
php artisan route:list --except-vendor # sembunyikan rute bawaan paket
php artisan route:list --json | jq # untuk diproses lebih lanjut
| Gejala | Penyebab yang paling sering |
|---|---|
| 404 padahal rutenya ada | Tertutup rute berparameter di atasnya, atau route:cache basi |
| 405 Method Not Allowed | Form mengirim POST ke rute PUT โ butuh @method('PUT') |
| 419 Page Expired | Token CSRF hilang atau kedaluwarsa (Fase 4) |
route:cache gagal | Ada closure di file rute โ pindahkan ke controller |
Latihan: buat Route::resource('produk', ...), jalankan php artisan route:list --path=produk,
dan cocokkan ketujuh barisnya dengan tabel di atas. Lalu tambahkan rute /produk/terlaris di bawah
rute {produk}, buka URL-nya, dan perbaiki dengan memindahkan urutannya.
Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.