Dua ekstensi PHP bisa dipakai untuk terhubung ke MySQL: PDO dan MySQLi. Artikel ini membandingkan keduanya sekaligus memberi contoh koneksi yang siap dipakai.
Menghubungkan PHP ke MySQL cukup ditulis dalam satu berkas kecil, tapi pilihan ekstensinya menentukan gaya kode kamu selama proyek berjalan. PHP menyediakan dua jalur resmi: PDO dan MySQLi. Keduanya bisa dipakai sekarang, dan keduanya punya kelebihan berbeda tergantung kebutuhan.
Kalau kamu baru mulai, bagian tersulit biasanya bukan menulis baris koneksinya, melainkan memutuskan mana yang dipakai dan bagaimana menangani kegagalan koneksi tanpa membocorkan detail ke pengguna.
PDO dan MySQLi: Apa Bedanya
PDO (PHP Data Objects) adalah lapisan abstraksi database. Kamu menulis kode yang sama untuk MySQL, PostgreSQL, atau SQLite, hanya string DSN yang berubah. MySQLi dibuat khusus untuk MySQL, jadi ia bisa memakai fitur yang tidak tersedia lewat PDO, termasuk panggilan asinkron dan API berorientasi objek yang lebih dekat ke protokol MySQL.
Perbedaan praktisnya muncul di tiga hal. Dukungan driver, gaya penulisan kode, dan cara menangani prepared statement. Untuk proyek yang mungkin pindah database di kemudian hari, PDO menghemat banyak penulisan ulang. Untuk proyek yang jelas akan tetap di MySQL dan butuh fitur spesifiknya, MySQLi lebih langsung.
Dukungan driver
PDO butuh ekstensi pdo_mysql aktif. MySQLi butuh mysqli aktif. Cek dengan php -m di terminal atau lewat phpinfo(). Kalau salah satu tidak muncul, aktifkan di php.ini lalu jalankan ulang server. Cara menjalankan PHP sendiri bisa berbeda-beda tergantung setup, dan itu dibahas di 7 Cara Menjalankan PHP Tanpa Apache.
Gaya penulisan kode
MySQLi menyediakan dua gaya: prosedural dan objek. PDO hanya berorientasi objek. Kalau kamu menulis kode baru, gaya objek lebih mudah dibaca dan konsisten.
| Aspek | PDO | MySQLi |
|---|---|---|
| Jenis database | Banyak | MySQL saja |
| Prepared statement | Ya, named parameter | Ya, positional parameter |
| Gaya kode | Objek | Objek dan prosedural |
| Panggilan asinkron | Tidak | Ya |
Contoh Koneksi dengan PDO
PDO memakai DSN untuk menentukan driver, host, nama database, dan charset. Bagian charset penting karena banyak masalah karakter aneh di database berasal dari pengaturan ini.
<?php
$host = '127.0.0.1';
$db = 'toko';
$user = 'root';
$pass = '';
$charset = 'utf8mb4';
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
$pdo = new PDO($dsn, $user, $pass, $options);
} catch (PDOException $e) {
error_log($e->getMessage());
exit('Koneksi database gagal.');
}
Tiga opsi di atas mengubah perilaku default PDO. ERRMODE_EXCEPTION membuat kesalahan dilempar sebagai exception, bukan diam-diam gagal. FETCH_ASSOC mengembalikan array asosiatif tanpa kolom duplikat. EMULATE_PREPARES dimatikan supaya prepared statement benar-benar diproses server MySQL, bukan disimulasikan di sisi PHP.
Perhatikan blok catch: pesan asli masuk ke log, sedangkan pengguna hanya melihat pesan umum. Detail seperti nama host dan user tidak boleh tampil di halaman publik.
Contoh Koneksi dengan MySQLi
Versi objek dari MySQLi lebih ringkas, tapi kamu kehilangan named parameter. Semua placeholder ditulis sebagai tanda tanya.
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
try {
$mysqli = new mysqli('127.0.0.1', 'root', '', 'toko');
$mysqli->set_charset('utf8mb4');
} catch (mysqli_sql_exception $e) {
error_log($e->getMessage());
exit('Koneksi database gagal.');
}
Baris mysqli_report() mengubah MySQLi agar melempar exception alih-alih mengembalikan nilai false secara diam-diam. Tanpa itu, kamu harus memeriksa hasil setiap panggilan satu per satu, dan itu mudah terlupa.
Kesalahan Umum Saat Pertama Kali Menyambung
Empat masalah berikut paling sering muncul. Semuanya bisa diperiksa dalam hitungan menit.
- Akses ditolak. User, password, atau host tidak cocok. Di MySQL, user
rootlewatlocalhostdan127.0.0.1bisa diperlakukan berbeda karena soket versus TCP. - Database tidak ditemukan. Nama database di DSN salah ketik, atau kamu lupa membuatnya.
- Karakter rusak. Charset belum diset ke
utf8mb4, sehingga emoji dan aksara non-Latin tersimpan sebagai tanda tanya. - Koneksi terlalu banyak. Setiap request membuka koneksi baru. Untuk aplikasi dengan trafik ramai, gunakan connection pool atau koneksi persisten dengan hati-hati.
Jika pesan error yang muncul membingungkan, aktifkan mode debug sementara. Perbandingan antara mencetak variabel, Xdebug, dan logger dijelaskan di Perbandingan Cara Debug PHP: Var Dump, Xdebug, dan Logger. Untuk melihat isi query yang gagal, tangkap exception dan catat pesan aslinya ke berkas log.
Menyimpan Kredensial di Luar Kode
Menulis user dan password langsung di berkas koneksi berbahaya kalau proyek diunggah ke repositori publik. Pindahkan nilainya ke variabel lingkungan atau berkas .env yang tidak ikut ter-commit. Alternatif lain, termasuk memakai berkas konfigurasi terpisah dan secrets manager, dibandingkan di 7 Cara Menyimpan Konfigurasi Database di PHP.
Kode koneksi sebaiknya juga tidak dibuat ulang di setiap berkas. Buat satu fungsi atau kelas yang mengembalikan objek koneksi, lalu panggil dari tempat lain. Pola ini memudahkan penggantian kredensial tanpa menyentuh banyak berkas.
Mana yang Sebaiknya Dipakai
Untuk proyek baru yang belum terikat database tertentu, PDO lebih aman dipilih. Named parameter membuat query panjang lebih mudah dibaca, dan dukungan multi-database memberi ruang gerak tanpa penulisan ulang besar. MySQLi masuk akal kalau kamu yakin akan tetap di MySQL dan ingin memakai fitur seperti koneksi asinkron atau API spesifik MySQL lainnya.
Apa pun pilihannya, dua hal berlaku sama: gunakan prepared statement untuk semua input dari pengguna, dan jangan pernah tampilkan pesan error database ke halaman publik. Sisanya soal selera dan kebutuhan proyek.
Pertanyaan yang Sering Diajukan
Apakah PDO lebih lambat daripada MySQLi?
Selisih performanya kecil dan jarang terasa di aplikasi biasa. Kalau EMULATE_PREPARES dimatikan, PDO mengirim query ke MySQL dengan cara yang mirip MySQLi. Bottleneck biasanya ada di query dan indeks, bukan di lapisan koneksi.
Bolehkah memakai koneksi persisten?
Bisa, tapi pahami risikonya. Koneksi persisten tidak ditutup di akhir request, sehingga bisa menghemat waktu pembukaan koneksi. Masalahnya, transaksi yang tidak selesai atau state sesi bisa bocor ke request berikutnya. Pakai hanya kalau kamu mengelola transaksi dengan disiplin.
Bagaimana cara tahu koneksi berhasil?
Jalankan query sederhana seperti SELECT 1 setelah koneksi dibuat. Kalau tidak melempar exception, koneksi dan autentikasi sudah benar. Jangan mengandalkan tidak adanya pesan error saja, karena beberapa konfigurasi bisa gagal tanpa suara.