Ketika halaman website menampilkan data kosong, error 500, atau tombol simpan seolah tidak bekerja, reaksi paling umum adalah langsung mengubah beberapa bagian kode sekaligus. Masalahnya, cara ini sering membuat kita kehilangan petunjuk. Setelah itu, kita tidak lagi tahu perubahan mana yang memperbaiki masalah dan perubahan mana yang justru menambah bug baru.
Debugging yang baik bukan sekadar mencari baris kode yang salah. Debugging adalah proses membuktikan di titik mana aliran data berhenti: apakah input tidak masuk, PHP gagal memproses, query MySQL tidak sesuai, atau respons API tidak ditangani dengan benar oleh JavaScript.
Mulai dari gejala, bukan dugaan
Langkah pertama adalah menulis gejala secara spesifik. “Website rusak” terlalu luas untuk dijadikan petunjuk. Ubah menjadi keterangan yang bisa diuji, misalnya: “form berhasil dikirim, tetapi kolom user_id tersimpan sebagai NULL” atau “endpoint mengembalikan status 200, tetapi array items kosong”.
Pisahkan pula tiga hal berikut:
- Input: data yang dikirim pengguna atau aplikasi lain.
- Proses: validasi, logika PHP, dan query database.
- Output: data yang disimpan, respons JSON, atau tampilan di browser.
Pemisahan ini membantu kita menguji sistem secara bertahap. Jika input sudah salah, tidak ada gunanya langsung mengoptimalkan query. Sebaliknya, jika query terbukti benar tetapi halaman tetap kosong, perhatian bisa dialihkan ke JavaScript atau format respons.
Periksa input yang benar-benar diterima PHP
Nilai yang terlihat di form belum tentu sama dengan nilai yang diterima server. Nama atribut name yang keliru, metode request yang berbeda, atau data JSON yang belum didekode dapat membuat variabel PHP berisi nilai kosong.
Untuk pengujian lokal, catat isi request secara terkontrol:
<?php
error_log(json_encode([
'method' => $_SERVER['REQUEST_METHOD'] ?? null,
'post' => $_POST,
'raw' => file_get_contents('php://input')
]));Jangan menampilkan data sensitif seperti kata sandi, token, atau nomor kartu ke layar maupun log produksi. Log sebaiknya membantu menemukan masalah tanpa menciptakan risiko baru.
Jika request menggunakan JSON, PHP tidak otomatis menaruh isinya di $_POST. Data perlu dibaca dari body request dan diubah menjadi array:
$payload = json_decode(file_get_contents('php://input'), true);Setelah itu, validasi tipe dan keberadaan field sebelum menjalankan query. Pesan error seperti “field email wajib diisi” jauh lebih berguna daripada error database yang muncul beberapa langkah kemudian.
Gunakan exception agar kegagalan tidak diam-diam
PDO menyediakan beberapa mode penanganan error. Mode exception membuat kegagalan database dilempar sebagai PDOException, sehingga alur error lebih mudah dilacak. Dokumentasi PHP mencatat bahwa PDO::ERRMODE_EXCEPTION menjadi mode default sejak PHP 8.0, tetapi menetapkannya secara eksplisit tetap membuat konfigurasi aplikasi lebih jelas.
$pdo = new PDO($dsn, $username, $password, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);Di lingkungan pengembangan, tampilkan detail error secukupnya. Di produksi, simpan detail teknis ke log dan kirim pesan umum kepada pengguna. Jangan menampilkan nama tabel, kredensial koneksi, atau path server pada halaman publik.
Uji query dengan data yang sama
Query yang gagal di aplikasi belum tentu gagal ketika dijalankan di aplikasi database. Penyebabnya sering kali adalah nilai parameter, koneksi ke database yang berbeda, atau kondisi WHERE yang terlalu ketat.
Gunakan prepared statement dan parameter terikat, bukan menggabungkan input pengguna ke dalam string SQL:
$stmt = $pdo->prepare(
'SELECT id, name FROM users WHERE email = :email LIMIT 1'
);
$stmt->execute(['email' => $email]);
$user = $stmt->fetch();Prepared statement membantu memisahkan template SQL dari nilai input. Namun, itu bukan pengganti validasi. Email tetap perlu diperiksa formatnya, ID perlu dipastikan berupa angka yang masuk akal, dan hak akses tetap harus diverifikasi di sisi server.
Saat debugging, catat nama operasi dan parameter yang aman untuk dicatat. Hindari mencatat seluruh query setelah parameter sensitif ditempelkan ke dalamnya. Tujuannya adalah memperoleh konteks, bukan membuat log menjadi salinan data pengguna.
Gunakan EXPLAIN untuk masalah yang terasa lambat
Jika query menghasilkan data yang benar tetapi halaman lambat, jangan langsung menambah server atau mengubah banyak indeks. Jalankan EXPLAIN untuk melihat rencana eksekusi MySQL. Perintah ini menunjukkan bagaimana optimizer memperkirakan cara membaca tabel, menggunakan indeks, dan menggabungkan data.
EXPLAIN
SELECT orders.id, orders.created_at
FROM orders
WHERE orders.user_id = 42
ORDER BY orders.created_at DESC
LIMIT 20;Perhatikan apakah kolom yang sering dipakai dalam WHERE, JOIN, atau ORDER BY memiliki indeks yang relevan. Jangan menganggap setiap indeks selalu mempercepat aplikasi. Terlalu banyak indeks juga menambah pekerjaan saat data ditulis dan dapat meningkatkan penggunaan ruang.
Untuk pengujian yang membutuhkan perbandingan estimasi dengan kondisi nyata, MySQL menyediakan EXPLAIN ANALYZE pada jenis perintah tertentu. Gunakan dengan hati-hati dan lakukan pada lingkungan yang aman, terutama jika query tidak hanya membaca data.
Bedakan error API dan error tampilan
API yang mengembalikan respons HTTP 200 belum tentu mengirim data yang benar. Bisa saja server mengirim JSON berisi – Rio Yotto @rioyotto{Sumber & bacaan lebih lanjut
