Sepanjang Section Routing dan Request, kita menangani request memakai closure langsung di dalam routes/web.php. Pendekatan tersebut cepat untuk route kecil, tetapi aplikasi nyata punya puluhan endpoint dengan logika yang tidak muat di satu baris closure. Laravel menyediakan controller: kelas PHP khusus yang menampung logika penanganan request dalam bentuk method. Chapter ini membahas tugas sebenarnya sebuah controller di dalam pola MVC, tugas yang justru bukan miliknya, serta filosofi thin controller yang menjaga kode kita tetap sehat saat aplikasi membesar.
Posisi Controller dalam MVC #
Laravel mengikuti pola arsitektur MVC (Model–View–Controller) yang membagi tanggung jawab aplikasi web menjadi tiga lapisan. Controller adalah lapisan perantara: aplikasi menerima request, router memilih route yang cocok, lalu router mendelegasikan pekerjaan ke method controller. Tugas inti controller hanyalah satu — mengoordinasikan perjalanan request menjadi response. Secara konkret, koordinasi tersebut berarti tiga kegiatan: membaca input dari request, memanggil lapisan lain untuk memproses data, lalu memilih bentuk response yang dikembalikan.
Perjalanan satu request melalui controller dapat kita petakan sebagai berikut:
| Tahap | Pelaku | Tanggung jawab |
|---|---|---|
| 1 | Router | Mencocokkan method + URI, memilih method controller |
| 2 | Middleware | Menyaring request sebelum controller berjalan |
| 3 | Controller | Membaca input, memanggil model/service, menyusun response |
| 4 | Model / Service | Mengakses database dan menjalankan logika bisnis |
| 5 | View | Merender HTML dari data yang diteruskan controller |
Controller berada di tengah alur tersebut, tetapi posisi tengah bukan berarti semua pekerjaan dilakukan di sana. Bayangkan controller sebagai security sebuah gedung: ia menerima tamu, memeriksa identitas, mengarahkan tamu ke lantai yang tepat, lalu mencatat kegiatan — security tidak ikut mengerjakan pekerjaan karyawan di setiap lantai.
Pembatasan peran ini juga terasa saat menguji aplikasi. Method controller yang hanya berisi koordinasi dapat diuji dengan feature test ringkas, karena keputusannya — input apa yang dibaca, lapisan mana yang dipanggil, response apa yang dikembalikan — sedikit dan terbaca. Sebaliknya, controller yang menampung query, perhitungan, sampai penyusunan HTML menghasilkan test yang panjang dan rapuh: satu perubahan kecil pada query ikut meruntuhkan assertion untuk presentasi, meskipun keduanya tidak berhubungan.
Tugas yang Bukan Milik Controller #
Karena controller mudah diakses dan bebas menulis kode apa pun, kode di dalamnya cenderung menumpuk tanpa kita sadari. Empat kategori pekerjaan berikut sebaiknya tidak ditulis di controller, karena Laravel menyediakan tempat yang lebih tepat:
| Kategori | Tempat yang tepat | Alasan |
|---|---|---|
| Logika bisnis (hitung diskon, alur pendaftaran) | Service / Action class | Bisa dipakai ulang dari queue, command, maupun API |
| Akses data (query, simpan, hapus) | Model Eloquent / query builder | Terpusat, mudah diuji, tidak digandakan |
| Presentasi (format tampilan) | View / Blade | Tampilan berubah tanpa menyentuh logika |
| Validasi input (chapter lanjutan) | FormRequest | Aturan terpisah per jenis request |
Pemisahan tersebut terasa berlebihan pada aplikasi dua route, tetapi terbayar saat fitur bertambah: logika pendaftaran yang dipakai ulang oleh halaman web dan endpoint API cukup ditulis satu kali di service class, dan perubahan aturan presentasi tidak pernah merusak logika bisnis.
Filosofi Thin Controller #
Prinsip yang kita pegang sepanjang Section ini adalah thin controller — controller tipis sebagai koordinator, bukan pelaksana. Sebuah method controller yang sehat terlihat seperti membaca daftar periksa singkat: ambil input, serahkan ke lapisan lain, kembalikan response. Perhatikan contoh method berikut:
public function store(Request $request, DaftarkanPengguna $daftarkan): RedirectResponse
{
$pengguna = $daftarkan->eksekusi(
nama: $request->input('nama'),
email: $request->input('email'),
password: $request->input('password'),
);
return redirect()
->route('pendaftaran.sukses')
->with('status', "Selamat bergabung, {$pengguna->name}!");
}Method di atas hanya membaca tiga input, mendelegasikan pekerjaan ke class DaftarkanPengguna, lalu membangun redirect — seluruhnya selesai dalam beberapa baris tanpa satu pun query database atau perhitungan bisnis. Detail cara kerja class DaftarkanPengguna dan kenapa pendekatan ini kuat kita bahas tuntas di chapter Separation of Concerns di akhir Section ini.
Dengan batas tugas yang jelas, kita siap menulis controller sungguhan. Seluruh kemampuan controller Laravel resmi terdokumentasi di dokumentasi controllers — dan langkah pertamanya adalah membuat berkas controller lewat Artisan, topik chapter Membuat Controller berikutnya.