Bayangkan sebuah gedung dengan beberapa pos pemeriksaan: resepsionis memeriksa tanda pengenal, satpam memeriksa tas, baru kamu boleh masuk ke ruangan. Di Laravel, middleware adalah pos-pos pemeriksaan itu bagi setiap permintaan HTTP sebelum (dan sesudah) mencapai controller.
Cara kerja middleware
Permintaan melewati serangkaian middleware seperti lapisan bawang, mencapai controller di pusat, lalu respons kembali melewati lapisan yang sama dalam urutan terbalik.
Request → Middleware A → Middleware B → Controller
Response ← Middleware A ← Middleware B ←
Setiap middleware bisa:
- Meneruskan permintaan ke lapisan berikutnya (
$next($request)). - Menghentikan permintaan dan langsung mengembalikan respons (misalnya redirect ke login atau 403).
- Mengubah permintaan sebelum diteruskan, atau mengubah respons setelah controller selesai.
Laravel sendiri memakai middleware untuk banyak hal: sesi, CSRF, enkripsi cookie, autentikasi (auth), pembatasan laju (throttle), dan verifikasi email.
Membuat middleware
php artisan make:middleware EnsureUserIsAdmin
File dibuat di app/Http/Middleware/EnsureUserIsAdmin.php:
class EnsureUserIsAdmin
{
public function handle(Request $request, Closure $next): Response
{
if (! $request->user() || ! $request->user()->is_admin) {
abort(403, 'Hanya admin yang boleh mengakses halaman ini.');
}
return $next($request);
}
}
Kuncinya ada pada $next($request): tanpa memanggilnya, permintaan berhenti di sini.
Mendaftarkan middleware
Laravel 10 dan sebelumnya: app/Http/Kernel.php
// Global: dijalankan pada setiap request
protected $middleware = [ ... ];
// Alias untuk dipakai di route
protected $middlewareAliases = [ // (di Laravel 9 bernama $routeMiddleware)
'admin' => \App\Http\Middleware\EnsureUserIsAdmin::class,
];
// Grup: 'web' dan 'api'
protected $middlewareGroups = [ ... ];
Laravel 11 dan lebih baru: bootstrap/app.php
->withMiddleware(function (Middleware $middleware) {
$middleware->alias(['admin' => EnsureUserIsAdmin::class]);
})
Memakai middleware pada route
Route::get('/dashboard', [DashboardController::class, 'index'])
->middleware('auth');
Route::middleware(['auth', 'admin'])->prefix('admin')->group(function () {
Route::get('/pengguna', [UserController::class, 'index']);
Route::resource('produk', ProdukController::class);
});
Urutan dalam array menentukan urutan eksekusi: di atas, auth berjalan sebelum admin, sehingga admin selalu punya $request->user() yang valid.
Middleware juga bisa dipasang di constructor controller atau diabaikan pada route tertentu dengan ->withoutMiddleware(...).
Middleware dengan parameter
Parameter dipisahkan titik dua dan koma:
Route::get('/laporan', ...)->middleware('role:admin,manager');
public function handle(Request $request, Closure $next, string ...$roles): Response
{
if (! in_array($request->user()?->role, $roles)) {
abort(403);
}
return $next($request);
}
Before dan after middleware
Kode sebelum $next berjalan sebelum controller (validasi, otorisasi). Kode sesudah berjalan setelah respons dibuat (logging, menambah header).
public function handle(Request $request, Closure $next): Response
{
$mulai = microtime(true);
$response = $next($request); // controller berjalan di sini
$durasi = round((microtime(true) - $mulai) * 1000);
$response->headers->set('X-Response-Time', $durasi . 'ms');
return $response;
}
Kasus penggunaan nyata
| Kebutuhan | Pendekatan middleware |
|---|---|
| Hanya pengguna login | auth bawaan |
| Pembatasan peran (admin, editor) | Middleware dengan parameter peran |
| Maintenance per fitur | Cek flag konfigurasi, kembalikan 503 |
| Pembatasan laju API | throttle:60,1 |
| Log aktivitas | After middleware yang menyimpan jejak |
| Pengaturan bahasa | Baca header/ sesi lalu app()->setLocale() |
| Memaksa HTTPS | Redirect jika ! $request->secure() |
| Header keamanan | Tambahkan CSP, X-Frame-Options pada respons |
| Verifikasi API key | Periksa header sebelum meneruskan |
Terminable middleware
Jika sebagian pekerjaan boleh dilakukan setelah respons dikirim (misalnya menyimpan log berat), implementasikan method terminate($request, $response). Pengguna tidak menunggu proses itu.
Menguji middleware
public function test_non_admin_ditolak(): void
{
$user = User::factory()->create(['is_admin' => false]);
$this->actingAs($user)->get('/admin/pengguna')->assertForbidden();
}
Kesalahan umum
- Lupa
return $next($request)sehingga halaman kosong. - Mengira middleware
authberjalan padahal belum didaftarkan di group yang benar. - Menaruh logika bisnis berat di middleware. Middleware sebaiknya ringan, tugasnya menyaring.
- Urutan salah: middleware yang butuh user dipasang sebelum
auth. - Mengandalkan middleware saja untuk otorisasi data. Gunakan juga policy/gate untuk memeriksa hak atas objek tertentu.
Contoh lengkap: middleware peran dengan pesan yang ramah
php artisan make:middleware CekPeran
class CekPeran
{
public function handle(Request $request, Closure $next, string ...$peran): Response
{
$user = $request->user();
if (! $user) {
return redirect()->guest(route('login'));
}
if (! in_array($user->peran, $peran, true)) {
if ($request->expectsJson()) {
return response()->json(['message' => 'Anda tidak berhak mengakses ini.'], 403);
}
abort(403, 'Anda tidak berhak mengakses halaman ini.');
}
return $next($request);
}
}
Penggunaan:
Route::get('/laporan', LaporanController::class)->middleware('peran:admin,manajer');
Perhatikan bahwa middleware yang sama menangani dua jenis klien: browser (halaman error) dan API (JSON), dengan memeriksa expectsJson().
Middleware vs Policy vs Gate
| Alat | Menjawab pertanyaan | Contoh |
|---|---|---|
| Middleware | "Apakah permintaan ini boleh masuk ke rute ini?" | Hanya admin yang boleh /admin/* |
| Gate | "Apakah pengguna boleh melakukan aksi ini?" (aturan umum) | Gate::allows('lihat-laporan') |
| Policy | "Apakah pengguna boleh melakukan aksi pada objek ini?" | Hanya pemilik yang boleh mengubah artikelnya |
Gunakan middleware untuk gerbang kasar di tingkat route, dan policy untuk keputusan per-objek di dalam controller.
Urutan dan prioritas
Urutan eksekusi mengikuti urutan pendaftaran: middleware global lebih dulu, lalu middleware group (web/api), lalu middleware route. Jika kamu butuh mengatur urutan tertentu, gunakan properti $middlewarePriority pada Kernel (Laravel 10) atau $middleware->priority([...]) (Laravel 11).
Debugging middleware
- Gunakan
php artisan route:list -vuntuk melihat middleware yang terpasang di tiap route. - Tambahkan
dd($request->user())sementara untuk memeriksa nilai pada titik tertentu. - Jika route terasa "tidak terlindungi", periksa apakah ia berada di dalam grup
Route::middleware(...)yang benar, dan apakah ada cache route lama (php artisan route:clear).
Kesimpulan
Middleware adalah mekanisme elegan untuk logika yang berlaku di banyak route tanpa mengulang kode di tiap controller. Pahami alur request-response berlapis, daftarkan alias, dan gunakan parameter untuk membuatnya fleksibel. Untuk autentikasi lengkap yang bergantung pada middleware ini, baca Membuat Authentication Laravel.
Komentar (0)
Masuk / Daftar