1. Code
  2. Coding Fundamentals
  3. Databases & SQL

PDO vs MySQLi: Mana yang Harus Anda Gunakan?

Saat mengakses database di PHP, kita memiliki dua pilihan: MySQLi dan PDO. Jadi apa yang harus Anda ketahui sebelum memilih salah satunya? Masalah kekhawatiran perbedaan, dukungan database, stabilitas dan kinerja akan dibahas dalam artikel ini.
Scroll to top

Indonesian (Bahasa Indonesia) translation by ⚡ Rova Rindrata (you can also view the original English article)

Saat mengakses database di PHP, kita memiliki dua pilihan: MySQLi dan PDO. Jadi apa yang harus Anda ketahui sebelum memilih salah satunya? Masalah kekhawatiran perbedaan, dukungan database, stabilitas dan kinerja akan dibahas dalam artikel ini.


Ringkasan

PDO MySQLi
Dukungan database 12 driver berbeda Hanya MySQL
API OOP OOP + prosedural
Koneksi Mudah Mudah
Parameter bernama Ya Tidak
Pemetaan objek Ya Ya
Prepared statements
(sisi client)
Ya Tidak
Kinerja Cepat Cepat
Stored procedures Ya Ya

Koneksi

Sangat mudah untuk terhubung ke database dengan keduanya:

1
// PDO

2
$pdo = new PDO("mysql:host=localhost;dbname=database", 'username', 'password');
3
4
// mysqli, procedural way

5
$mysqli = mysqli_connect('localhost','username','password','database');
6
7
// mysqli, object oriented way

8
$mysqli = new mysqli('localhost','username','password','database');

Harap dicatat bahwa obyek-obyek koneksi/sumber daya ini akan dianggap selalu ada sampai akhir dari tutorial ini.


Dukungan API

PDO dan MySQLi menawarkan API berorientasi obyek, tapi MySQLi juga menawarkan API prosedural - yang membuatnya lebih mudah dipahami bagi pemula. Jika Anda sudah familiar dengan driver PHP MySQL yang asli, Anda akan menemukan migrasi ke antarmuka MySQLi prosedural jauh lebih mudah. Di sisi lain, setelah Anda menguasai PDO, Anda dapat menggunakannya dengan setiap database yang Anda inginkan!


Dukungan Database

Keuntungan utama dari PDO dari MySQLi adalah dalam dukungannya terhadap driver database. Pada saat penulisan ini, PDO mendukung 12 driver berbeda, berlawanan dengan MySQLi, yang hanya mendukung MySQL.

Untuk mencetak daftar semua driver PDO yang saat ini didukung, gunakan kode berikut:

1
var_dump(PDO::getAvailableDrivers());

Apa artinya ini? Nah, dalam situasi ketika Anda harus mengalihkan proyek Anda menggunakan database lain, PDO membuat proses menjadi transparan. Jadi yang hanya harus Anda lakukan adalah perubahan koneksi string dan beberapa query - jika mereka menggunakan metode yang tidak didukung oleh database baru Anda. Dengan MySQLi, Anda akan perlu untuk menulis ulang setiap potongan kode - termasuk query.


Parameter Bernama

Ini adalah fitur penting lain yang memiliki PDO; mengikat parameter jauh lebih mudah daripada menggunakan pengikatan angka:

1
$params = array(':username' => 'test', ':email' => $mail, ':last_login' => time() - 3600);
2
  
3
$pdo->prepare('

4
	SELECT * FROM users

5
	WHERE username = :username

6
	AND email = :email

7
	AND last_login > :last_login');
8
	
9
$pdo->execute($params);

...berlawanan dengan cara MySQLi:

1
$query = $mysqli->prepare('

2
	SELECT * FROM users

3
	WHERE username = ?

4
	AND email = ?

5
	AND last_login > ?');
6
	
7
$query->bind_param('sss', 'test', $mail, time() - 3600);
8
$query->execute();

Pengikatan parameter tanda tanya mungkin tampak lebih pendek, tetapi tidak hampir sefleksibel parameter bernama, karena fakta bahwa pengembang harus selalu melacak urutan parameter; rasanya "hacky" dalam beberapa keadaan.

Sayangnya, MySQLi tidak mendukung parameter bernama.


Pemetaan Objek

PDO dan MySQLi dapat memetakan hasil dalam bentuk obyek. Hal ini sangat berguna jika Anda tidak ingin menggunakan lapisan abstraksi database kustom, tapi masih ingin perilaku seperti-ORM. Mari kita bayangkan bahwa kita memiliki class User dengan beberapa properti, yang cocok dengan nama field dari database.

1
class User {
2
	public $id;
3
	public $first_name;
4
	public $last_name;
5
	
6
	public function info()
7
	{
8
		return '#'.$this->id.': '.$this->first_name.' '.$this->last_name;
9
	}
10
}

Tanpa pemetaan obyek, kita perlu untuk mengisi setiap nilai field (baik secara manual atau melalui konstruktor) sebelum kita dapat menggunakan metode info() dengan benar.

Hal ini memungkinkan kita untuk menentukan properti dahulu bahkan sebelum obyek dibangun! Misalnya:

1
$query = "SELECT id, first_name, last_name FROM users";
2
	
3
// PDO

4
$result = $pdo->query($query);
5
$result->setFetchMode(PDO::FETCH_CLASS, 'User');
6
7
while ($user = $result->fetch()) {
8
	echo $user->info()."\n";
9
}
10
// MySQLI, procedural way

11
if ($result = mysqli_query($mysqli, $query)) {
12
	while ($user = mysqli_fetch_object($result, 'User')) {
13
		echo $user->info()."\n";
14
	}
15
}
16
// MySQLi, object oriented way

17
if ($result = $mysqli->query($query)) {
18
	while ($user = $result->fetch_object('User')) {
19
		echo $user->info()."\n";
20
	}
21
}

Keamanan

Kedua library menyediakan keamanan injeksi SQL,  asalkan pengembang menggunakan mereka dengan cara yang mereka maksudkan (baca: escaping / parameter yang mengikat dengan prepared statements).

Misalnya seorang hacker mencoba untuk menyuntikkan beberapa SQL berbahaya melalui parameter query HTTP 'username' (GET):

1
$_GET['username'] = "'; DELETE FROM users; /*"

Jika kita gagal untuk meng-escape ini, maka akan disertakan dalam pencarian "sebagaimana adanya" - menghapus semua baris dari tabel users (PDO dan mysqli mendukung beberapa query).

1
// PDO, "manual" escaping

2
$username = PDO::quote($_GET['username']);
3
4
$pdo->query("SELECT * FROM users WHERE username = $username");
5
		
6
// mysqli, "manual" escaping

7
$username = mysqli_real_escape_string($_GET['username']);
8
9
$mysqli->query("SELECT * FROM users WHERE username = '$username'");

Seperti yang Anda lihat, PDO::quote() tidak hanya meng-escape string, tetapi juga meng-quote-nya. Di sisi lain, mysqli_real_escape_string() hanya akan meng-escape string, Anda akan perlu untuk menerapkan quote secara manual.

1
// PDO, prepared statement

2
$pdo->prepare('SELECT * FROM users WHERE username = :username');
3
$pdo->execute(array(':username' => $_GET['username']));
4
5
// mysqli, prepared statements

6
$query = $mysqli->prepare('SELECT * FROM users WHERE username = ?');
7
$query->bind_param('s', $_GET['username']);
8
$query->execute();

Saya sarankan bahwa Anda selalu menggunakan prepared statements dengan query terikat daripada PDO::quote() dan mysqli_real_escape_string().


Kinerja

Sementara PDO dan MySQLi cukup cepat, MySQLi tanpa signifikan lebih cepat dalam benchmark - ~2.5% untuk non-prepared statements, dan ~6.5% untuk prepared statements. Bagaimanapun juga, ekstensi MySQL asli lebih cepat daripada keduanya. Jadi jika Anda benar-benar perlu untuk memeras kinerja sampai titik terakhir, itu adalah satu hal yang mungkin Anda pertimbangkan.


Ringkasan

Pada akhirnya, PDO memenangkan pertempuran ini dengan mudah. Dengan dukungan untuk dua belas driver database yang berbeda (delapan belas database berbeda!) dan parameter bernama, kita dapat mengabaikan kerugian kecil di kinerja, dan akan terbiasa dengan API-nya. Dari sudut pandang keamanan, keduanya aman asalkan pengembang menggunakan mereka dengan cara yang seharusnya digunakan (baca: prepared statements).

Jadi jika Anda masih bekerja dengan MySQLi, mungkin ini adalah waktu untuk perubahan!