PHP menawarkan tiga API berbeda untuk terhubung ke MySQL. Ini adalah mysql(dihapus pada PHP 7) mysqli,, dan PDOekstensi.
The mysql_*fungsi yang digunakan untuk menjadi sangat populer, tetapi penggunaannya tidak dianjurkan lagi. Tim dokumentasi sedang membahas situasi keamanan basis data, dan mendidik pengguna untuk menjauh dari ekstensi ext / mysql yang umum digunakan adalah bagian dari ini (lihat php.internals: deprecating ext / mysql ).
Dan tim pengembang PHP kemudian telah mengambil keputusan untuk menghasilkan E_DEPRECATEDkesalahan ketika pengguna terhubung ke MySQL, apakah melalui mysql_connect(), mysql_pconnect()atau fungsi koneksi implisit yang dibangun ext/mysql.
ext/mysqlsecara resmi tidak digunakan lagi pada PHP 5.5 dan telah dihapus pada PHP 7 .
Lihat Kotak Merah?
Ketika Anda melanjutkan mysql_* halaman manual fungsi, Anda melihat kotak merah, menjelaskannya tidak boleh digunakan lagi.
Mengapa
Beranjak dari ext/mysqltidak hanya tentang keamanan, tetapi juga tentang memiliki akses ke semua fitur dari database MySQL.
ext/mysqldibangun untuk MySQL 3.23 dan hanya mendapat sedikit tambahan sejak saat itu sementara sebagian besar menjaga kompatibilitas dengan versi lama ini yang membuat kode sedikit lebih sulit untuk dipelihara. Fitur yang hilang yang tidak didukung oleh ext/mysqltermasuk: ( dari manual PHP ).
Alasan untuk tidak menggunakan mysql_*fungsi :
- Tidak dalam pengembangan aktif
- Dihapus pada PHP 7
- Tidak memiliki antarmuka OO
- Tidak mendukung kueri tak-blokir dan asinkron
- Tidak mendukung pernyataan yang disiapkan atau permintaan parameter
- Tidak mendukung prosedur tersimpan
- Tidak mendukung banyak pernyataan
- Tidak mendukung transaksi
- Tidak mendukung semua fungsi di MySQL 5.1
Poin di atas dikutip dari jawaban Quentin
Kurangnya dukungan untuk pernyataan yang disiapkan sangat penting karena memberikan metode yang lebih jelas, lebih tidak rentan untuk melarikan diri dan mengutip data eksternal daripada secara manual menghindarinya dengan pemanggilan fungsi yang terpisah.
Lihat perbandingan ekstensi SQL .
Menekan peringatan penghentian
Saat kode sedang dikonversi ke MySQLi/ PDO, E_DEPRECATEDkesalahan bisa ditekan dengan menetapkan error_reportingdi php.ini untuk dikecualikanE_DEPRECATED:
error_reporting = E_ALL ^ E_DEPRECATED
Perhatikan bahwa ini juga akan menyembunyikan peringatan penghentian lainnya , yang, bagaimanapun, mungkin untuk hal-hal selain MySQL. ( dari manual PHP )
Artikel PDO vs MySQLi: Yang Harus Anda Gunakan? oleh Dejan Marjanovic akan membantu Anda memilih.
Dan cara yang lebih baik adalah PDO, dan sekarang saya sedang menulis PDOtutorial sederhana .
Tutorial PDO sederhana dan pendek
Q. Pertanyaan pertama yang ada di pikiran saya adalah: apa itu `PDO`?
A. " PDO - Objek Data PHP - adalah lapisan akses basis data yang menyediakan metode seragam untuk akses ke banyak basis data."

Menghubungkan ke MySQL
Dengan mysql_*fungsi atau kita dapat mengatakannya dengan cara lama (tidak digunakan lagi dalam PHP 5.5 dan lebih tinggi)
$link = mysql_connect('localhost', 'user', 'pass');
mysql_select_db('testdb', $link);
mysql_set_charset('UTF-8', $link);
Dengan PDO: Yang perlu Anda lakukan adalah membuat PDOobjek baru . Konstruktor menerima parameter untuk menentukan PDOkonstruktor sumber database kebanyakan mengambil empat parameter yaitu DSN(nama sumber data) dan secara opsional username,password .
Di sini saya pikir Anda sudah terbiasa dengan semua kecuali DSN; ini baru dalam PDO. A DSNpada dasarnya adalah serangkaian opsi yang memberi tahu PDOdriver mana yang harus digunakan, dan detail koneksi. Untuk referensi lebih lanjut, periksa PDO MySQL DSN .
$db = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'username', 'password');
Catatan: Anda juga dapat menggunakan charset=UTF-8, tetapi terkadang menyebabkan kesalahan, jadi lebih baik digunakanutf8 .
Jika ada kesalahan koneksi, itu akan melempar PDOExceptionobjek yang bisa ditangkap untuk menangani Exceptionlebih lanjut.
Bacaan baik : Koneksi dan Manajemen koneksi ¶
Anda juga dapat mengirimkan beberapa opsi driver sebagai larik ke parameter keempat. Saya sarankan meneruskan parameter yang menempatkan PDOke mode pengecualian. Karena beberapa PDOpengemudi tidak mendukung pernyataan persiapan asli, jadi PDOlakukan persaingan persiapan. Ini juga memungkinkan Anda mengaktifkan emulasi ini secara manual. Untuk menggunakan pernyataan yang disiapkan di sisi server asli, Anda harus mengaturnya secara eksplisit false.
Yang lain adalah untuk menonaktifkan persiapan emulasi yang diaktifkan di MySQLdriver secara default, tetapi mempersiapkan emulasi harus dimatikan untuk digunakan PDOdengan aman.
Saya nanti akan menjelaskan mengapa persiapan persaingan harus dimatikan. Untuk menemukan alasan silakan periksa posting ini .
Ini hanya dapat digunakan jika Anda menggunakan versi lama MySQLyang tidak saya rekomendasikan.
Di bawah ini adalah contoh bagaimana Anda dapat melakukannya:
$db = new PDO('mysql:host=localhost;dbname=testdb;charset=UTF-8',
'username',
'password',
array(PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
Bisakah kita menetapkan atribut setelah konstruksi PDO?
Ya , kami juga dapat menetapkan beberapa atribut setelah konstruksi PDO dengan setAttributemetode:
$db = new PDO('mysql:host=localhost;dbname=testdb;charset=UTF-8',
'username',
'password');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
Penanganan Kesalahan
Menangani kesalahan jauh lebih mudah PDOdaripada mysql_*.
Praktik umum saat menggunakan mysql_*adalah:
//Connected to MySQL
$result = mysql_query("SELECT * FROM table", $link) or die(mysql_error($link));
OR die()bukan cara yang baik untuk menangani kesalahan karena kita tidak dapat menangani masalahnya die. Ini hanya akan mengakhiri skrip tiba-tiba dan kemudian mengulangi kesalahan ke layar yang biasanya Anda TIDAK ingin ditampilkan kepada pengguna akhir Anda, dan biarkan peretas berdarah menemukan skema Anda. Sebagai alternatif, nilai-nilai mysql_*fungsi yang kembali sering dapat digunakan bersama dengan mysql_error () untuk menangani kesalahan.
PDOmenawarkan solusi yang lebih baik: pengecualian. Apa pun yang kita lakukan PDOharus dibungkus dengan try- catchblok. Kita dapat memaksa PDOke salah satu dari tiga mode kesalahan dengan mengatur atribut mode kesalahan. Tiga mode penanganan kesalahan ada di bawah ini.
PDO::ERRMODE_SILENT. Itu hanya mengatur kode kesalahan dan bertindak hampir sama dengan di mysql_*mana Anda harus memeriksa setiap hasil dan kemudian melihat $db->errorInfo();untuk mendapatkan detail kesalahan.
PDO::ERRMODE_WARNINGAngkat E_WARNING. (Peringatan run-time (kesalahan non-fatal). Eksekusi skrip tidak dihentikan.)
PDO::ERRMODE_EXCEPTION: Melempar pengecualian. Ini merupakan kesalahan yang diangkat oleh PDO. Anda tidak boleh melempar PDOExceptiondari kode Anda sendiri. Lihat Pengecualian untuk informasi lebih lanjut tentang pengecualian dalam PHP. Kerjanya sangat mirip or die(mysql_error());, ketika tidak tertangkap. Tapi tidak seperti itu or die(), PDOExceptiondapat ditangkap dan ditangani dengan anggun jika Anda memilih untuk melakukannya.
Bagus dibaca :
Suka:
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
Dan Anda dapat membungkusnya dalam try- catch, seperti di bawah ini:
try {
//Connect as appropriate as above
$db->query('hi'); //Invalid query!
}
catch (PDOException $ex) {
echo "An Error occured!"; //User friendly message/message you want to show to user
some_logging_function($ex->getMessage());
}
Anda tidak harus menangani try- catchsekarang. Anda dapat menangkapnya kapan saja sesuai, tetapi saya sangat menyarankan Anda untuk menggunakan try- catch. Juga mungkin lebih masuk akal untuk menangkapnya di luar fungsi yang memanggil PDObarang:
function data_fun($db) {
$stmt = $db->query("SELECT * FROM table");
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
//Then later
try {
data_fun($db);
}
catch(PDOException $ex) {
//Here you can handle error and show message/perform action you want.
}
Juga, Anda dapat menangani or die()atau kita dapat mengatakan suka mysql_*, tetapi itu akan sangat bervariasi. Anda dapat menyembunyikan pesan kesalahan berbahaya dalam produksi dengan memutar display_errors offdan hanya membaca log kesalahan Anda.
Sekarang, setelah membaca semua hal di atas, Anda mungkin berpikir: apa sih adalah bahwa ketika saya hanya ingin memulai bersandar sederhana SELECT, INSERT, UPDATE, atau DELETEpernyataan? Jangan khawatir, ini dia:
Memilih Data

Jadi yang Anda lakukan mysql_*adalah:
<?php
$result = mysql_query('SELECT * from table') or die(mysql_error());
$num_rows = mysql_num_rows($result);
while($row = mysql_fetch_assoc($result)) {
echo $row['field1'];
}
Sekarang PDO, Anda dapat melakukan ini seperti:
<?php
$stmt = $db->query('SELECT * FROM table');
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
echo $row['field1'];
}
Atau
<?php
$stmt = $db->query('SELECT * FROM table');
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
//Use $results
Catatan : Jika Anda menggunakan metode seperti di bawah ini ( query()), metode ini mengembalikan PDOStatementobjek. Jadi jika Anda ingin mengambil hasilnya, gunakan seperti di atas.
<?php
foreach($db->query('SELECT * FROM table') as $row) {
echo $row['field1'];
}
Dalam Data PDO, diperoleh melalui ->fetch()metode penanganan pernyataan Anda. Sebelum menelepon mengambil, pendekatan terbaik adalah memberi tahu PDO bagaimana Anda ingin data diambil. Pada bagian di bawah ini saya menjelaskan ini.
Ambil Mode
Perhatikan penggunaan PDO::FETCH_ASSOCdalam fetch()dan fetchAll()kode di atas. Ini memberitahu PDOuntuk mengembalikan baris sebagai array asosiatif dengan nama bidang sebagai kunci. Ada banyak mode pengambilan lainnya yang akan saya jelaskan satu per satu.
Pertama-tama, saya jelaskan bagaimana memilih mode pengambilan:
$stmt->fetch(PDO::FETCH_ASSOC)
Di atas, saya telah menggunakan fetch(). Anda juga bisa menggunakan:
Sekarang saya datang untuk mengambil mode:
PDO::FETCH_ASSOC: mengembalikan array yang diindeks oleh nama kolom seperti yang dikembalikan di set hasil Anda
PDO::FETCH_BOTH (default): mengembalikan array yang diindeks dengan nama kolom dan nomor kolom yang diindeks 0 seperti yang dikembalikan di set hasil Anda
Bahkan ada lebih banyak pilihan! Baca tentang semuanya di PDOStatementAmbil dokumentasi. .
Mendapatkan jumlah baris :
Alih-alih menggunakan mysql_num_rowsuntuk mendapatkan jumlah baris yang dikembalikan, Anda bisa mendapatkan PDOStatementdan melakukannya rowCount(), seperti:
<?php
$stmt = $db->query('SELECT * FROM table');
$row_count = $stmt->rowCount();
echo $row_count.' rows selected';
Mendapatkan ID yang Terakhir Dimasukkan
<?php
$result = $db->exec("INSERT INTO table(firstname, lastname) VAULES('John', 'Doe')");
$insertId = $db->lastInsertId();
Sisipkan dan Perbarui atau Hapus pernyataan

Apa yang kami lakukan dalam mysql_*fungsi adalah:
<?php
$results = mysql_query("UPDATE table SET field='value'") or die(mysql_error());
echo mysql_affected_rows($result);
Dan di pdo, hal yang sama dapat dilakukan oleh:
<?php
$affected_rows = $db->exec("UPDATE table SET field='value'");
echo $affected_rows;
Dalam kueri di atas, PDO::execjalankan pernyataan SQL dan kembalikan jumlah baris yang terpengaruh.
Sisipkan dan hapus akan dibahas nanti.
Metode di atas hanya berguna ketika Anda tidak menggunakan variabel dalam kueri. Tetapi ketika Anda perlu menggunakan variabel dalam kueri, jangan pernah mencoba seperti di atas dan di sana untuk pernyataan disiapkan atau pernyataan parameter .
Pernyataan Disiapkan
Q. Apa pernyataan yang disiapkan dan mengapa saya membutuhkannya?
A. Pernyataan yang disiapkan adalah pernyataan SQL pra-kompilasi yang dapat dieksekusi beberapa kali dengan mengirimkan hanya data ke server.
Alur kerja khas menggunakan pernyataan yang disiapkan adalah sebagai berikut ( dikutip dari Wikipedia tiga poin 3 ):
Mempersiapkan : Templat pernyataan dibuat oleh aplikasi dan dikirim ke sistem manajemen basis data (DBMS). Nilai-nilai tertentu dibiarkan tidak ditentukan, disebut parameter, placeholder atau variabel terikat (berlabel di ?bawah):
INSERT INTO PRODUCT (name, price) VALUES (?, ?)
DBMS mem-parsing, mengkompilasi, dan melakukan optimisasi kueri pada template pernyataan, dan menyimpan hasilnya tanpa menjalankannya.
- Jalankan : Di lain waktu, aplikasi memasok (atau mengikat) nilai untuk parameter, dan DBMS mengeksekusi pernyataan (mungkin mengembalikan hasil). Aplikasi dapat menjalankan pernyataan sebanyak yang diinginkan dengan nilai yang berbeda. Dalam contoh ini, ini mungkin menyediakan 'Roti' untuk parameter pertama dan
1.00untuk parameter kedua.
Anda bisa menggunakan pernyataan yang disiapkan dengan menyertakan placeholder dalam SQL Anda. Pada dasarnya ada tiga yang tanpa penampung (jangan coba ini dengan variabel di atas satu), satu dengan penampung yang tidak disebutkan namanya, dan satu dengan penampung yang disebutkan.
P. Jadi sekarang, apa yang disebut placeholder dan bagaimana cara menggunakannya?
A. Penampung yang ditunjuk. Gunakan nama deskriptif yang didahului dengan titik dua, bukan tanda tanya. Kami tidak peduli dengan posisi / urutan nilai pada pemegang nama tempat:
$stmt->bindParam(':bla', $bla);
bindParam(parameter,variable,data_type,length,driver_options)
Anda juga dapat mengikat menggunakan array eksekusi:
<?php
$stmt = $db->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->execute(array(':name' => $name, ':id' => $id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
Fitur bagus lain untuk OOPteman adalah placeholder yang diberi nama memiliki kemampuan untuk menyisipkan objek langsung ke database Anda, dengan asumsi properti cocok dengan bidang yang disebutkan. Sebagai contoh:
class person {
public $name;
public $add;
function __construct($a,$b) {
$this->name = $a;
$this->add = $b;
}
}
$demo = new person('john','29 bla district');
$stmt = $db->prepare("INSERT INTO table (name, add) value (:name, :add)");
$stmt->execute((array)$demo);
Q. Jadi sekarang, apa saja placeholder tanpa nama dan bagaimana cara menggunakannya?
A. Mari kita punya contoh:
<?php
$stmt = $db->prepare("INSERT INTO folks (name, add) values (?, ?)");
$stmt->bindValue(1, $name, PDO::PARAM_STR);
$stmt->bindValue(2, $add, PDO::PARAM_STR);
$stmt->execute();
dan
$stmt = $db->prepare("INSERT INTO folks (name, add) values (?, ?)");
$stmt->execute(array('john', '29 bla district'));
Di atas, Anda dapat melihat itu ?alih - alih nama seperti pada tempat tempat nama. Sekarang dalam contoh pertama, kami menetapkan variabel ke berbagai placeholder ( $stmt->bindValue(1, $name, PDO::PARAM_STR);). Kemudian, kami memberikan nilai kepada placeholder tersebut dan menjalankan pernyataan tersebut. Dalam contoh kedua, elemen array pertama pergi ke yang pertama ?dan yang kedua ke yang kedua ?.
CATATAN : Di placeholder tanpa nama, kita harus menjaga urutan elemen yang tepat dalam array yang kita lewati ke PDOStatement::execute()metode.
SELECT, INSERT, UPDATE, DELETEDisiapkan query
SELECT:
$stmt = $db->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->execute(array(':name' => $name, ':id' => $id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
INSERT:
$stmt = $db->prepare("INSERT INTO table(field1,field2) VALUES(:field1,:field2)");
$stmt->execute(array(':field1' => $field1, ':field2' => $field2));
$affected_rows = $stmt->rowCount();
DELETE:
$stmt = $db->prepare("DELETE FROM table WHERE id=:id");
$stmt->bindValue(':id', $id, PDO::PARAM_STR);
$stmt->execute();
$affected_rows = $stmt->rowCount();
UPDATE:
$stmt = $db->prepare("UPDATE table SET name=? WHERE id=?");
$stmt->execute(array($name, $id));
$affected_rows = $stmt->rowCount();
CATATAN:
Namun PDOdan / atau MySQLitidak sepenuhnya aman. Periksa jawabannya. Apakah pernyataan yang disiapkan PDO cukup untuk mencegah injeksi SQL? oleh ircmaxell . Juga, saya mengutip beberapa bagian dari jawabannya:
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo->query('SET NAMES GBK');
$stmt = $pdo->prepare("SELECT * FROM test WHERE name = ? LIMIT 1");
$stmt->execute(array(chr(0xbf) . chr(0x27) . " OR 1=1 /*"));