Berkas bootstrap/app.php memberi kita tiga cara memasang middleware, dan ketiganya memiliki jangkauan berbeda: ada yang menyaring setiap request tanpa terkecuali, ada yang hanya menyertai route web atau api, dan ada yang hanya menunggu di satu route. Kesalahan memilih lingkup berakibat dua arah — logika penting terlewat pada route tertentu, atau sebaliknya request yang tidak butuh ikut diproses berat. Chapter ini memetakan ketiga lingkup tersebut dengan data nyata dari aplikasi latihan, lalu menutupnya dengan panduan memilih.

Tiga Lingkup Pemasangan #

AspekGlobalGroup (web, api)Route-specific
Cara daftar$middleware->append(...)$middleware->web(append: ...)->middleware(...) pada route
JangkauanSemua requestRoute yang terdaftar di file grup tersebutRoute itu saja
Contoh bawaanTrimStrings, HandleCorsStartSession, PreventRequestForgeryauth, throttle, middleware buatan kita
Cocok untukKebersihan & keamanan dasarKebutuhan khas web atau apiAturan bisnis spesifik

Ketiganya tidak saling menggantikan, melainkan bersarang satu di dalam yang lain: lapisan global membungkus group, dan group membungkus middleware route. Sebuah request ke /tugas pada akhirnya melewati tiga sabuk pengaman sekaligus — normalisasi input dari global, session dari group web, lalu pemeriksaan token dari route — dan masing-masing boleh menghentikan perjalanan kapan pun. Semakin ke dalam lapisan, semakin spesifik keputusannya; global hanya tahu hal-hal yang berlaku untuk semua orang.

Isi Bawaan Laravel #

Laravel sudah membekali aplikasi baru dengan deretan middleware bawaan. Karena tidak ada perintah artisan khusus untuk menampilkannya, kita gunakan objek Kernel dari snippet kecil berikut:

php
$kernel = $app->make(Illuminate\Foundation\Http\Kernel::class);

echo "== GLOBAL ==\n";
foreach ($kernel->getGlobalMiddleware() as $m) { echo $m, "\n"; }

echo "\n== GROUPS ==\n";
foreach ($kernel->getMiddlewareGroups() as $name => $list) {
    echo "[{$name}]\n";
    foreach ($list as $m) { echo "  ", $m, "\n"; }
}

Output yang Dihasilkan:

text
== GLOBAL ==
Illuminate\Http\Middleware\ValidatePathEncoding
Illuminate\Foundation\Http\Middleware\InvokeDeferredCallbacks
Illuminate\Http\Middleware\TrustProxies
Illuminate\Http\Middleware\HandleCors
Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance
Illuminate\Http\Middleware\ValidatePostSize
Illuminate\Foundation\Http\Middleware\TrimStrings
Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull

== GROUPS ==
[web]
  Illuminate\Cookie\Middleware\EncryptCookies
  Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse
  Illuminate\Session\Middleware\StartSession
  Illuminate\View\Middleware\ShareErrorsFromSession
  Illuminate\Foundation\Http\Middleware\PreventRequestForgery
  Illuminate\Routing\Middleware\SubstituteBindings
[api]
  Illuminate\Routing\Middleware\SubstituteBindings

Deretan global menangani hal-hal yang berlaku untuk semua lalu lintas: normalisasi input, CORS, dan pemeriksaan ukuran POST. Group web lebih tebal karena halaman browser butuh cookie terenkripsi, session, dan proteksi CSRF — sedangkan group api ramping: tanpa session dan CSRF, hanya route model binding.

Mari kita baca isi group web satu per satu karena setiap anggotanya punya alasan kuat. EncryptCookies mengenkripsi isi cookie di sisi browser, AddQueuedCookiesToResponse memasang cookie yang dibuat sepanjang request, dan StartSession menyalakan session yang menjadi fondasi login. ShareErrorsFromSession membagikan variabel $errors ke semua view, PreventRequestForgery menolak POST lintas situs tanpa token CSRF, dan SubstituteBindings menyelesaikan route model binding. Group api tidak butuh sebagian besar itu — client API tidak menyimpan cookie maupun membaca halaman — sehingga cukup mengandalkan SubstituteBindings plus middleware yang kita tempelkan sendiri.

Memeriksa Middleware Aktif #

Untuk melihat middleware apa saja yang menempel pada route, route:list dengan flag -v adalah alat utama kita:

bash
php artisan route:list -v

Output yang Dihasilkan:

text
  GET|HEAD  / .............................................. routes/web.php:14
            ⇂ web
  POST      admin/artikel .................................. routes/web.php:48
            ⇂ web
            ⇂ App\Http\Middleware\EnsureRole:editor,create
  GET|HEAD  api/laporan/{id} ................................ routes/api.php:8
            ⇂ api
            ⇂ App\Http\Middleware\IpWhitelist
            ⇂ App\Http\Middleware\ForceJsonResponse
            ⇂ App\Http\Middleware\RequestLogger
  GET|HEAD  tugas ........................................... routes/web.php:30
            ⇂ web
            ⇂ App\Http\Middleware\EnsureTokenIsValid

Setiap tanda ⇂ adalah satu lapisan: group di atas, middleware route di bawahnya. Route / hanya membawa group web; /tugas membawa group plus middleware token; dan route api membawa group api dengan tiga middleware kustom.

Menguji Lingkup dengan Test #

Test berikut memetakan empat route dan mencatat jejak tiga penanda: header dari middleware global, header dari middleware group web, dan header dari middleware route:

php
$baris = [
    ['/up (tanpa grup)', $this->get('/up')],
    ['/', $this->get('/')],
    ['/tugas', $this->get('/tugas?token=rahasia-budi')],
    ['/api/laporan/9', $this->get('/api/laporan/9')],
];

foreach ($baris as [$label, $response]) {
    printf(
        "%-16s global=%s web=%s route-mw=%s\n",
        $label,
        $response->headers->get('X-Global-Mw') ?? '-',
        $response->headers->get('X-Web-Group') ?? '-',
        $response->headers->get('X-Token-Checked') ?? '-',
    );
}

Output yang Dihasilkan:

text
/up (tanpa grup) global=aktif web=- route-mw=-
/                global=aktif web=aktif route-mw=-
/tugas           global=aktif web=aktif route-mw=ya
/api/laporan/9   global=aktif web=- route-mw=-

Pola pada output tersebut merangkum ketiga lingkup: kolom global terisi di semua baris, kolom web hanya pada route web, dan penanda route middleware hanya muncul di /tugas yang benar-benar memasangnya.

Memilih Lingkup yang Tepat #

Pertanyaan penentunya sederhana: berapa banyak request yang butuh logika ini?

  1. Semua request — kebersihan input, header keamanan, penanganan maintenance: masuk global.
  2. Semua route web atau semua route api — session, CSRF, format khusus API: masuk group.
  3. Sebagian kecil route — syarat token, batasan peran, whitelist alamat: cukup menempel pada route atau route group.

Patokan tambahannya soal risiko: middleware global yang menolak request salah bisa melumpuhkan seluruh aplikasi, jadi logika penyaring ketat seperti whitelist IP jangan pernah dinaikkan ke global. Sebaliknya, middleware yang aman dan murah seperti pencatatan akses justru paling berguna saat memantau semua request. Perubahan lingkup juga sebaiknya disertai test yang menetapkan ekspektasi secara eksplisit, seperti tabel pada bagian sebelumnya, agar route baru tidak lolos dari pengawasan tanpa disadari.

Middleware route juga menerima argumen seperti role:admin yang terlihat pada output route:list di atas. Sintaks parameter inilah yang kita bedah tuntas pada chapter berikutnya. Rujukan resmi ada di dokumentasi middleware .