Route di chapter sebelumnya selalu menunjuk URI tetap seperti /tugas. Aplikasi nyata jarang sesederhana itu: kita perlu halaman seperti /tugas/5 untuk tugas nomor 5 atau /pengguna/budi/tugas/12 untuk satu tugas milik satu pengguna. Membuat satu route untuk setiap kemungkinan nilai jelas tidak masuk akal. Route parameter menyelesaikan masalah ini dengan menandai segmen URI sebagai placeholder yang nilainya ditangkap saat request datang dan diteruskan ke handler sebagai argumen. Chapter ini membahas parameter wajib, beberapa parameter sekaligus, parameter opsional dengan nilai default, sampai cara parameter hidup berdampingan dengan dependency injection.
Parameter Wajib #
Placeholder ditulis di dalam kurung kurawal, misalnya {id}, dan nama placeholder tersebut otomatis dikirim ke handler sebagai argumen bernama sama. Tambahkan dua route berikut ke routes/web.php:
<?php
use Illuminate\Support\Facades\Route;
// Parameter wajib tunggal
Route::get('/tugas/{id}', function (string $id) {
return "Tugas nomor {$id}";
});
// Beberapa parameter wajib sekaligus
Route::get('/pengguna/{pengguna}/tugas/{tugas}', function (string $pengguna, string $tugas) {
return "Tugas {$tugas} milik pengguna {$pengguna}";
});Route pertama menuntut URI /tugas/ diikuti satu segmen apa pun; route kedua menangkap dua segmen {pengguna} dan {tugas} dari posisinya masing-masing di URI. Karena keduanya wajib, request tanpa segmen tersebut tidak akan pernah cocok — router menjawabnya dengan 404. Perlu dicatat bahwa nilai parameter selalu datang sebagai string, meskipun isinya angka; konversi ke int menjadi tanggungan handler bila dibutuhkan.
Parameter Opsional dengan Nilai Default #
Kadang segmen boleh tidak hadir. Tanda tanya setelah nama placeholder — {kategori?} — menjadikannya opsional, dan nilai default kita tulis langsung di signature handler:
// Parameter opsional dengan nilai default
Route::get('/kategori/{kategori?}', function (?string $kategori = 'umum') {
return "Kategori: {$kategori}";
});Saat segmen tidak ada, handler menerima 'umum'; saat segmen ada, handler menerima nilainya. Karena parameter opsional boleh absen, tipe parameternya harus nullable (?string).
Parameter Route dan Dependency Injection #
Handler route juga bisa menerima dependency dari service container — misalnya objek Request — cukup dengan menuliskan type declaration-nya di signature. Tambahkan use Illuminate\Http\Request; di bagian atas routes/web.php, lalu daftarkan dua route berikut yang menguji apakah urutan penulisan berpengaruh:
// Dependency duluan, parameter route belakangan
Route::get('/perangkat/{id}', function (Request $request, string $id) {
return [
'id' => $id,
'path' => $request->path(),
];
});
// Urutan terbalik: parameter route duluan
Route::get('/urutan/{id}', function (string $id, Request $request) {
return "id={$id}, punya objek Request: ".($request instanceof Request ? 'ya' : 'tidak');
});Kita uji seluruh route di atas sekaligus dengan skrip uji-route.php yang sama dengan chapter sebelumnya — daftar $permintaan kali ini berisi delapan kombinasi URI:
<?php
// uji-route.php — jalankan dari root proyek Laravel
use Illuminate\Contracts\Http\Kernel;
use Illuminate\Http\Request;
require __DIR__.'/vendor/autoload.php';
$app = require __DIR__.'/bootstrap/app.php';
$kernel = $app->make(Kernel::class);
$permintaan = [
['GET', '/tugas/5'],
['GET', '/tugas/abc'],
['GET', '/tugas'],
['GET', '/pengguna/budi/tugas/12'],
['GET', '/kategori'],
['GET', '/kategori/kantor'],
['GET', '/perangkat/7'],
['GET', '/urutan/9'],
];
foreach ($permintaan as [$method, $uri]) {
$response = $kernel->handle(
Request::create('http://localhost:8000'.$uri, $method)
);
$body = trim($response->getContent());
$isi = str_starts_with($body, '<!DOCTYPE') ? '(halaman error HTML)' : $body;
echo str_pad("{$method} {$uri}", 28)
." → HTTP ".$response->getStatusCode()
.' | '.$isi.PHP_EOL;
}Output yang Dihasilkan:
GET /tugas/5 → HTTP 200 | Tugas nomor 5
GET /tugas/abc → HTTP 200 | Tugas nomor abc
GET /tugas → HTTP 404 | (halaman error HTML)
GET /pengguna/budi/tugas/12 → HTTP 200 | Tugas 12 milik pengguna budi
GET /kategori → HTTP 200 | Kategori: umum
GET /kategori/kantor → HTTP 200 | Kategori: kantor
GET /perangkat/7 → HTTP 200 | {"id":"7","path":"perangkat\/7"}
GET /urutan/9 → HTTP 200 | id=9, punya objek Request: yaMari kita baca hasilnya baris demi baris. Baris pertama dan kedua membuktikan parameter wajib menerima nilai apa pun — 5 maupun abc — karena kita belum memasang aturan nilainya (topik chapter Route Constraints
). Baris ketiga mengonfirmasi segmen wajib yang hilang berujung 404. Baris keempat menunjukkan dua parameter tertangkap dari posinya. Dua baris kategori mendemonstrasikan nilai default 'umum' dan nilai hasil tangkapan 'kantor'. Terakhir, kedua route terbukti bekerja dengan urutan penulisan dependency yang berbeda-beda. Laravel membedakan dua macam argumen dari tipenya: objek yang bisa di-resolve service container seperti Request diinjeksi otomatis, sedangkan parameter bertipe skalar diisi dari placeholder yang namanya sama. Karena pencocokan berbasis nama, bukan posisi, string $id di depan maupun belakang Request $request sama-sama menerima nilai dari placeholder {id}. Output JSON {"id":"7",...} sekaligus memperlihatkan bahwa nilai parameter datang sebagai string "7".
Menutup chapter, route:list merangkum kelima route beserta tandanya:
php artisan route:list --except-vendorOutput yang Dihasilkan:
GET|HEAD kategori/{kategori?} .......................................... routes/web.php:17
GET|HEAD pengguna/{pengguna}/tugas/{tugas} ............................. routes/web.php:12
GET|HEAD perangkat/{id} ................................................ routes/web.php:22
GET|HEAD tugas/{id} ..................................................... routes/web.php:7
GET|HEAD urutan/{id} ................................................... routes/web.php:30
Showing [5] routesTanda tanya pada kategori/{kategori?} membedakan parameter opsional dari parameter wajib. Sejauh ini kita selalu memanggil route lewat URI-nya secara langsung — di link, form, dan redirect. Namun URI bisa berubah saat aplikasi tumbuh, dan mengubah satu URI berarti memburu semua tempat yang menuliskannya. Laravel punya solusi yang lebih aman: memberi nama pada route, topik chapter Named Routes
berikutnya.