Routing Lanjutan: Group, Resource & Model Binding
Mengelompokkan route, route resource (CRUD), apiResource, dan route model binding.
Route group: pengaturan bersama
Banyak route punya awalan URL, nama, atau middleware yang sama. Kelompokkan agar tidak mengulang:
Route::prefix('admin')
->name('admin.')
->middleware('auth')
->group(function () {
Route::get('/dashboard', [DashboardController::class, 'index'])->name('dashboard');
Route::resource('produk', ProdukController::class);
});
prefix('admin')— semua URL diawali/admin.name('admin.')— semua nama diawaliadmin.(jadiadmin.dashboard).middleware('auth')— hanya pengguna yang login.- Group boleh bersarang. Variasi lain:
controller(...),domain(...),whereNumber(...).
Menunjuk ke controller
use App\Http\Controllers\ProdukController;
Route::get('/produk', [ProdukController::class, 'index']); // class + nama method
Route::controller(ProdukController::class)->group(function () { // class sekali untuk banyak route
Route::get('/produk', 'index');
Route::get('/produk/{produk}', 'show');
});
Route resource: CRUD dalam satu baris
Route::resource('produk', ProdukController::class);
| Metode | URL | Method controller | Nama route |
|---|---|---|---|
| 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 |
Pilih sebagian saja: ->only(['index', 'show']) atau ->except(['destroy']).
apiResource
Untuk API (tanpa form HTML) tidak butuh create dan edit:
Route::apiResource('kategori', KategoriController::class); // index, store, show, update, destroy
Route model binding
Alih-alih menerima {id} lalu mencari sendiri, minta Laravel menyuntikkan objek model-nya:
use App\Models\Produk;
Route::get('/produk/{produk}', function (Produk $produk) {
return $produk; // sudah berupa model hasil query; 404 otomatis bila tidak ada
});
Syarat implicit binding: nama variabel di parameter fungsi ($produk) sama dengan nama segmen route ({produk}) dan bertipe model. Untuk mencari dengan kolom lain (mis. slug): {produk:slug}.
Route::get('/produk/{produk:slug}', [ProdukController::class, 'show'])->name('produk.show');
Binding dengan scope
Untuk route bersarang (/kategori/{kategori}/produk/{produk}), ->scopeBindings() memastikan produk memang milik kategori itu.
Soft-deleted dan batasan
Model yang di-soft delete tidak ditemukan oleh binding secara default; gunakan ->withTrashed() pada route bila diperlukan.
Tips
- Cek hasil group dengan
php artisan route:list. - Gunakan route resource sebagai standar; tambahkan route khusus sebelum baris resource agar tidak tertimpa oleh
/produk/{produk}.