Pola front controller menempatkan seluruh permintaan web pada satu titik masuk, yaitu satu berkas PHP yang bertugas membaca permintaan lalu memilih kode yang mengerjakannya. Topik ini membangun pola tersebut secara manual dengan tabel rute berbasis array, respons 404 untuk rute yang tidak dikenal, serta pengujian lewat server bawaan PHP. Setelah membacanya, alur satu permintaan dari browser sampai handler dapat dilacak dan direproduksi dari nol.
Masalah banyak titik masuk#
Aplikasi PHP tanpa pola biasanya menaruh satu berkas PHP untuk satu halaman, misalnya beranda.php, tentang.php, dan kontak.php. Server web menerjemahkan URL langsung menjadi nama berkas, sehingga setiap halaman baru berarti satu berkas baru di server. Susunan ini terasa mudah pada awalnya, tetapi menimbulkan tiga hambatan seiring bertambahnya aplikasi.
Hambatan pertama adalah duplikasi, karena kode yang berlaku untuk semua halaman seperti pemuatan konfigurasi dan pemeriksaan sesi harus disalin ke setiap berkas. Hambatan kedua menyangkut URL, karena nama berkas ikut terpampang di alamat dan mengubah nama berkas berarti mengubah URL yang sudah tersebar di banyak tempat. Hambatan ketiga adalah tidak adanya tempat alami untuk kode yang harus berjalan pada setiap permintaan, misalnya pembukaan koneksi basis data, karena setiap berkas dieksekusi sendiri-sendiri.
Front controller membalik susunan tersebut. Satu berkas menerima setiap permintaan, dan perbedaan antarhalaman berubah menjadi data yang dibaca skrip, bukan menjadi nama berkas di server. Konsekuensinya, kode yang berlaku umum cukup ditulis satu kali di depan, dan pemetaan URL ke kode berada di satu tempat yang mudah diperiksa.
Satu titik masuk untuk semua permintaan#
Dalam pola ini, index.php menjadi satu-satunya berkas yang dilayani server. Server bawaan PHP mendukung susunan tersebut lewat mode router. Dalam mode ini, server dijalankan dengan menyebut satu berkas PHP yang dipanggil untuk setiap permintaan, termasuk permintaan ke URL yang tidak menyebut nama berkas apa pun. Skrip itu membaca $_SERVER['REQUEST_URI'], mengambil bagian path dengan parse_url, lalu mencocokkan path tersebut dengan daftar rute yang dikenalnya.
Diagram berikut memperlihatkan alur satu permintaan dari browser sampai respons kembali.
Kotak tengah menunjukkan peran yang paling penting, yaitu mencocokkan path permintaan dengan tabel rute sebelum kode apa pun dieksekusi. Apabila path tidak dikenal, index.php tetap menangani permintaan, tetapi keluarannya berupa respons 404 dan bukan error karena berkas tidak ada. Dengan demikian, permintaan yang tidak sah tetap mendapat jawaban yang rapi dari aplikasi.
Tabel rute dan handler#
Rute disimpan sebagai array asosiatif yang kuncinya berupa path dan nilainya berupa handler, yakni fungsi yang mengerjakan satu rute. Kunci array menjadikan tabel rute sebagai daftar yang bisa dihitung dan diperiksa, sehingga rute yang boleh diakses tidak pernah datang dari luar skrip. Berkas berikut adalah front controller lengkap untuk aplikasi catatan.
<?php
declare(strict_types=1);
// tabel rute: path permintaan => handler yang mengerjakannya
$rute = [
'/beranda' => static function (): void {
echo 'Halaman beranda aplikasi catatan.' . PHP_EOL;
},
'/tentang' => static function (): void {
echo 'Aplikasi catatan sederhana untuk latihan PHP.' . PHP_EOL;
},
];
// ambil path permintaan; di CLI tidak ada permintaan HTTP sehingga dipakai '/beranda'
$path = parse_url($_SERVER['REQUEST_URI'] ?? '/beranda', PHP_URL_PATH) ?? '/beranda';
if (isset($rute[$path])) {
$rute[$path]();
} else {
http_response_code(404);
echo 'Rute ' . $path . ' tidak dikenal.' . PHP_EOL;
}Halaman beranda aplikasi catatan.Ekspresi ?? '/beranda' menangani eksekusi lewat CLI. Karena CLI tidak menerima permintaan HTTP, $_SERVER['REQUEST_URI'] tidak terisi, dan path beranda dipilih sebagai bawaan. Pada konteks web, parse_url dengan PHP_URL_PATH memisahkan path dari query string, sehingga URL seperti /beranda?halaman=2 tetap dicocokkan sebagai rute /beranda. Pencocokan dilakukan dengan isset pada tabel rute, sedangkan cabang else menjalankan http_response_code(404) sebelum mencetak pesan agar status HTTP yang dikirim benar.
Mencoba lewat server bawaan#
Perintah berikut menjalankan server pada port 8110 dengan index.php sebagai skrip router, lalu meminta tiga rute yang berbeda menggunakan curl.
# jalankan server bawaan dengan index.php sebagai skrip router
php -S localhost:8110 index.php >/dev/null 2>&1 &
sleep 1
# minta rute /beranda
curl -s http://localhost:8110/beranda
# minta rute /tentang
curl -s http://localhost:8110/tentang
# minta rute yang tidak terdaftar
curl -s http://localhost:8110/lupa
# periksa kode status HTTP rute yang tidak terdaftar
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8110/lupa
# hentikan server
kill %1Halaman beranda aplikasi catatan.
Aplikasi catatan sederhana untuk latihan PHP.
Rute /lupa tidak dikenal.
404Tiga permintaan menghasilkan tiga respons yang berbeda, dan semuanya melewati index.php yang sama. Dua rute pertama cocok dengan tabel dan menjalankan handler masing-masing, sedangkan rute ketiga tidak dikenal sehingga mendapat status 404 sebagaimana ditunjukkan baris terakhir keluaran. Karena server berhenti setelah perintah kill, percobaan dapat diulang kapan saja dengan hasil yang sama.
Kesalahan umum#
Tiga kesalahan berikut paling sering muncul saat membangun front controller pertama.
- Respons 404 dikirim tanpa
http_response_code(404). Halaman pesan tetap tampil, tetapi status HTTP-nya 200, sehingga mesin pencari dan alat pemantau menganggap rute itu sah. Perbaikannya adalah mengatur kode status sebelum mencetak pesan. - Path permintaan dipakai langsung untuk memuat berkas, misalnya
require $path . '.php'. Nilai tersebut berasal dari URL yang dikendalikan pengunjung, sehingga path berbahaya bisa menyusup. Perbaikannya adalah mencocokkan path dengan tabel rute dan hanya memuat kode yang ada di daftar. - Pencocokan rute memakai
$_SERVER['REQUEST_URI']apa adanya. Nilai itu masih memuat query string, sehingga/beranda?halaman=2tidak pernah cocok dengan kunci/beranda. Perbaikannya adalah memisahkan path denganparse_urlsebelum dicocokkan.
Ringkasan#
- Front controller memusatkan seluruh permintaan pada satu berkas masuk sehingga kode yang berlaku umum cukup ditulis satu kali dan pemetaan URL berada di satu tempat.
- Tabel rute berupa array asosiatif yang kuncinya path dan nilainya handler, sehingga rute yang sah selalu berasal dari daftar yang bisa diperiksa.
- Rute yang tidak dikenal dijawab dengan
http_response_code(404)beserta pesan yang jelas, bukan dengan error berkas tidak ada. - Mode router server bawaan PHP (
php -S localhost:8110 index.php) adalah cara termudah mencoba pola ini sebelum menyentuh konfigurasi server produksi.
Referensi#
- PHP built-in web server — PHP Manual — Dokumentasi server bawaan beserta mode router yang dipakai topik ini.
$_SERVER— PHP Manual — Daftar kunci informasi permintaan, termasukREQUEST_URI.- parse_url — PHP Manual
— Dokumentasi pemecahan URL menjadi komponen, termasuk
PHP_URL_PATH. - http_response_code — PHP Manual — Dokumentasi pengaturan kode status HTTP respons.