Di Membuat Router kita menulis router sendiri: daftar definisi rute yang dicocokkan terhadap metode dan URI permintaan, lalu handler yang cocok dipanggil. Routing Laravel dibangun di atas prinsip yang persis sama, tetapi dibekali lapisan fitur produksi — validasi parameter, reverse routing, grup, hingga pembatasan laju permintaan. Pada chapter ini kita akan membedah fitur-fitur tersebut satu per satu mulai dari closure paling sederhana, lalu menutup dengan perbandingan jujur terhadap router buatan sendiri.
Route Dasar dengan Closure #
Route didefinisikan di routes/web.php dengan method yang dinamai sesuai verb HTTP. Bentuk paling sederhana memakai closure sebagai handler, dan nilai yang dikembalikan closure menjadi isi respons.
<?php
// routes/web.php
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
return 'Selamat datang di Toko Buku';
});
Route::post('/keranjang', function () {
return 'Keranjang diperbarui';
});
Route::match(['get', 'post'], '/kontak', function () {
return 'Hubungi kami';
});
Route::view('/tentang', 'tentang', ['namaToko' => 'Toko Buku Budi']);
Route::redirect('/promo', '/katalog', 301);Mari kita bedah kelima barisnya:
Route::get('/', ...): hanya permintaan GET ke URI/yang cocok; nilai balik string langsung menjadi respons200 OK.Route::post('/keranjang', ...): permintaan GET ke/keranjangtidak akan cocok — Laravel menjawab405 Method Not Allowed, bukan menjalankan closure.Route::match([...], ...): mendaftarkan beberapa verb sekaligus untuk satu URI.Route::view(...): jalan pintas untuk route yang hanya menampilkan template tanpa logika — di sini templateresources/views/tentang.blade.phpmenerima variabel$namaToko.Route::redirect(...): mengalihkan permanen (301) dari URI lama ke URI baru tanpa controller.
Route Parameter dan Constraint #
Segmen URI yang dinamis ditulis dalam kurung kurawal dan otomatis diteruskan sebagai argumen closure. Kita sudah mengenal teknik ini sebagai placeholder regex di router mini; Laravel menambahkan constraint agar bentuk parameter bisa dipaksa sebelum handler dijalankan.
<?php
use Illuminate\Support\Facades\Route;
Route::get('/buku/{slug}', function (string $slug) {
return "Detail buku: {$slug}";
});
Route::get('/penulis/{id}', function (string $id) {
return "Profil penulis nomor {$id}";
})->where('id', '[0-9]+');
Route::get('/arsip/{tahun?}', function (?string $tahun = null) {
return 'Arsip tahun ' . ($tahun ?? 'semua');
});Tiga bentuk parameter di atas bekerja seperti ini:
{slug}: segmen apa pun setelah/buku/terikat ke variabel$slug— pencocokan default mengizinkan semua karakter selain/.->where('id', '[0-9]+'): URI seperti/penulis/abctidak cocok dan berujung 404, karena hanya digit yang lolos. Laravel juga menyediakan pintasan->whereNumber('id'),->whereAlpha('nama'), dan->whereUuid('token').{tahun?}dengan?string $tahun = null: parameter opsional — URI/arsipdan/arsip/2024keduanya cocok. Perhatikan penulisan nullable eksplisit?string $tahun = null, sesuai aturan PHP 8.4 yang kita bahas di Routing Parameters .
Named Route dan Helper route() #
Memberi nama pada route memungkinkan kita membangun URL dari nama, bukan menuliskan path secara manual. Teknik ini dikenal sebagai reverse routing: definisi rute menjadi satu-satunya sumber kebenaran bagi URL.
<?php
use App\Http\Controllers\BookController;
use Illuminate\Support\Facades\Route;
Route::get('/buku/{slug}', [BookController::class, 'show'])
->name('books.show');
// di controller, view, atau class lain mana pun:
$url = route('books.show', ['slug' => 'belajar-php-dasar']);
// menghasilkan: /buku/belajar-php-dasar
return redirect()->route('books.show', ['slug' => 'belajar-php-dasar']);Manfaatnya terasa saat path berubah: cukup ubah definisi /buku/{slug} menjadi /produk/{slug}, dan seluruh tautan maupun redirect yang memakai nama books.show ikut berubah tanpa disentuh satu per satu. Bila URL ditulis manual di banyak template, perubahan path menjadi perburuan string yang rawan ada yang terlewat. Router mini kita tidak punya mekanisme ini — di sana setiap tautan ditulis tangan — dan itulah salah satu alasan reverse routing menjadi standar di framework modern.
Mengarahkan Route ke Controller #
Closure nyaman untuk demo dan route kecil, tetapi aplikasi nyata mengarahkan hampir semua route ke controller agar logika bisa diuji dan diorganisir per fitur. Sintaksnya memakai pasangan array [NamaController::class, 'namaMethod'].
<?php
use App\Http\Controllers\BookController;
use Illuminate\Support\Facades\Route;
Route::get('/katalog', [BookController::class, 'index']);Bentuk array ini lebih aman daripada string seperti 'BookController@index' karena BookController::class ikut diperiksa oleh IDE dan static analysis — salah ketik nama class langsung ketahuan saat refactoring. Pembagian tanggung jawabnya sama dengan yang kita rancang di Controller Layer
: route hanya memetakan permintaan, controller berisi logika permintaan.
Route Model Binding #
Fitur khas Laravel yang menghemat banyak kode adalah route model binding: parameter route bertipe model Eloquent otomatis diambil dari database. Laravel mencocokkan nama segmen {book} dengan nama argumen $book, lalu menjalankan Book::findOrFail($id) di belakang layar.
<?php
use App\Http\Controllers\BookController;
use Illuminate\Support\Facades\Route;
Route::get('/buku/{book}', [BookController::class, 'show']);<?php
// app/Http/Controllers/BookController.php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\Book;
class BookController extends Controller
{
public function show(Book $book)
{
// $book sudah berupa instance Book, bukan sekadar id
return view('books.show', ['book' => $book]);
}
}Bila baris tidak ditemukan, Laravel otomatis menjawab 404 — pola “cari atau gagal” yang dulu kita tulis manual dengan findOrFail() di chapter database kini menyatu dengan routing. Kustomisasi juga tersedia, misalnya Route::get('/buku/{book:slug}', ...) agar pencocokan memakai kolom slug, atau binding eksplisit lewat Route::model() untuk kunci non-standar.
Route Group #
Ketika sekumpulan route berbagi awalan URI, middleware, atau prefiks nama, group mencegah kita menulis ulang atribut yang sama berulang kali. Semua route di dalam group() mewarisi atribut dari rantai method sebelumnya.
<?php
use App\Http\Controllers\DashboardController;
use App\Http\Controllers\ReportController;
use Illuminate\Support\Facades\Route;
Route::prefix('admin')
->middleware(['auth'])
->name('admin.')
->group(function () {
Route::get('/dashboard', [DashboardController::class, 'index'])->name('dashboard');
Route::get('/laporan', [ReportController::class, 'index'])->name('reports');
});Rantai di atas menghasilkan dua rute sekaligus dengan tiga atribut seragam:
->prefix('admin'): URI menjadi/admin/dashboarddan/admin/laporan.->middleware(['auth']): pengunjung yang belum login dialihkan ke halaman login sebelum controller dijalankan — konsep middleware yang sama dengan Middleware di framework mini.->name('admin.'): nama lengkap rute menjadiadmin.dashboarddanadmin.reports, sehingga pemanggilroute('admin.dashboard')tidak bentrok dengan rutedashboardbiasa.
Web Routes vs API Routes #
Laravel memisahkan definisi rute ke dalam dua berkas yang mewarisi perilaku berbeda. Pemisahan ini menegaskan kembali pembedaan aplikasi stateful dan stateless dari chapter Stateless vs Stateful .
| Aspek | routes/web.php | routes/api.php |
|---|---|---|
| Prefiks URI | tanpa prefiks | otomatis diawali /api |
| State | berbasis session dan cookie | stateless, tanpa session |
| Middleware bawaan | session, verifikasi CSRF, enkripsi cookie | pembatas laju throttle:api |
| Respons tipikal | HTML dari Blade | JSON |
| Cocok untuk | aplikasi web klasik, area admin | API untuk mobile app dan SPA |
Verifikasi CSRF pada web.php hanya berlaku untuk verb yang tidak aman (POST, PUT, PATCH, DELETE) — GET tetap bebas karena dianggap tidak mengubah state. Di api.php tidak ada perlindungan CSRF karena klien tidak memegang cookie session; keamanannya ditangani token yang kita bahas di chapter authentication nanti.
Fallback dan Rate Limiting #
Dua fitur kecil yang sering dilupakan sampai dibutuhkan: halaman penampung untuk URI yang tak cocok, dan pembatasan laju permintaan. Route::fallback() dijalankan ketika tidak ada satu pun rute yang cocok, menggantikan halaman 404 bawaan.
<?php
use Illuminate\Support\Facades\Route;
Route::fallback(function () {
return response('Halaman tidak ditemukan', 404);
});Rate limiting dibangun dari limiter bernama yang membatasi jumlah permintaan per selang waktu, lalu diterapkan ke route melalui middleware throttle. Definisi limiter dituliskan sekali saat aplikasi di-bootstrap (di Laravel modern melalui bootstrap/app.php atau service provider), dan middleware throttle:nama-limiter tinggal memakainya.
<?php
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
RateLimiter::for('katalog', function (Request $request) {
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
});<?php
use App\Http\Controllers\CatalogController;
use Illuminate\Support\Facades\Route;
Route::middleware('throttle:katalog')->group(function () {
Route::get('/katalog', [CatalogController::class, 'index']);
});Closure limiter di atas mengembalikan batas 60 permintaan per menit yang dihitung per pengguna — atau per alamat IP bila belum login. Ketika batas terlampaui, Laravel otomatis menjawab 429 Too Many Requests tanpa controller pernah dijalankan. Konsep pembatasan laju beserta strategi per-klien ini persis materi Rate Limiting
di Section REST API; Laravel menyediakan implementasinya sehingga kita tinggal menetapkan angkanya.
Perbandingan dengan Router Buatan Sendiri #
| Aspek | Router mini kita | Routing Laravel |
|---|---|---|
| Definisi rute | array berisi pola dan handler | method fluent per verb + berkas terpisah |
| Pencocokan | regex atau pemisahan string manual | pencocokan terkompilasi dengan cache rute |
| Parameter | diekstrak lalu diperiksa manual | {param} + where() + binding model otomatis |
| URL balik | tidak ada; tautan ditulis manual | named route + helper route() |
| Pengelompokan | tidak ada | prefix/middleware/name berantai |
| Perlindungan | tidak ada | fallback, throttle, CSRF per grup |
Tabel ini menegaskan pesan penting section kita: framework bukan sihir, melainkan automasi atas keputusan-keputusan yang pernah kita ambil manual. Membaca kode routing Laravel jadi lebih mudah karena setiap fiturnya punya padanan konseptual di router mini — yang berbeda hanyalah skala dan tingkat kenyamanan.
Ringkasan #
Kini kita menguasai penuh pintu masuk aplikasi Laravel: route closure dan controller, parameter dengan constraint, named route untuk reverse routing, route model binding, grup dengan prefix dan middleware, pemisahan web/API, fallback, hingga rate limiting. Setiap permintaan yang lolos dari gerbang ini akhirnya berujung pada satu kebutuhan: membaca dan menulis data. Kebutuhan itulah yang ditangani Eloquent, ORM resmi Laravel, pada chapter berikutnya.