mysqli atau PDO - apa pro dan kontra? [Tutup]

342

Di tempat kami, kami berpisah antara menggunakan mysqli dan PDO untuk hal-hal seperti pernyataan yang disiapkan dan dukungan transaksi. Beberapa proyek menggunakan satu, beberapa lainnya. Ada sedikit kemungkinan realistis bagi kita untuk pindah ke RDBMS lain.

Saya lebih suka PDO karena satu alasan yang memungkinkan parameter bernama untuk pernyataan yang disiapkan, dan sejauh yang saya tahu mysqli tidak.

Apakah ada pro dan kontra lain untuk memilih satu dari yang lain sebagai standar saat kami mengkonsolidasikan proyek kami untuk menggunakan hanya satu pendekatan?

Polsonby
sumber
5
Artikel ini akan membantu memilih mana yang akan digunakan. Jika Anda mempertimbangkan kinerja, ini dapat membantu Anda memilih.
ravi404
3
Sungguh lucu berapa banyak orang yang telah memilih dan membintangi pertanyaan yang "tidak konstruktif". Masalahnya, utas lengkapnya sangat konstruktif - mungkin moderator harus mempertimbangkan ini ketika menilai apakah sebuah pertanyaan adalah konstruktor atau bukan?
marlar
@marlar Saya sangat setuju dengan Anda! Ini memang masalah terbesar di StackOverflow. Pertanyaan / diskusi yang bagus selalu ditutup.
Sliq

Jawaban:

243

Nah, Anda bisa berdebat dengan aspek berorientasi objek, pernyataan yang disiapkan, fakta bahwa itu menjadi standar, dll. Tapi saya tahu bahwa sebagian besar waktu, meyakinkan seseorang bekerja lebih baik dengan fitur pembunuh. Jadi begitulah:

Hal yang sangat menyenangkan dengan PDO adalah Anda dapat mengambil data, menyuntikkannya secara otomatis ke suatu objek. Jika Anda tidak ingin menggunakan ORM (karena itu hanya skrip cepat) tetapi Anda suka pemetaan objek, itu SANGAT keren:

class Student {

    public $id;
    public $first_name;
    public $last_name

    public function getFullName() {
        return $this->first_name.' '.$this->last_name
    }
}

try 
{
    $dbh = new PDO("mysql:host=$hostname;dbname=school", $username, $password)

    $stmt = $dbh->query("SELECT * FROM students");

    /* MAGIC HAPPENS HERE */

    $stmt->setFetchMode(PDO::FETCH_INTO, new Student);


    foreach($stmt as $student)
    {
        echo $student->getFullName().'<br />';
    } 

    $dbh = null;
}
catch(PDOException $e)
{
    echo $e->getMessage();
}
e-satis
sumber
12
apakah ada perbedaan antara di atas dan $mysqliResult->fetch_object("student");?
Andy Fleming
2
@ e-satis tidak, saya menggunakan PHP. Bidang publik melanggar enkapsulasi, jadi AS A BEST PRACTICEitu hanya ... lol :) Google tidak menggunakan bidang publik, hanya pengakses : google-styleguide.googlecode.com/svn/trunk/… .
OZ_
6
@ e-satis: Maaf karena ikut campur tetapi getter dan setter diperlukan jika Anda ingin mengontrol apa yang terjadi ketika variabel diubah. Kalau tidak, Anda sederhana tidak dapat menjamin keadaan internal objek Anda (ini terutama masalah jika Anda memiliki objek lain di dalamnya). Ini sepenuhnya bahasa independen. @ OZ_: Bersantailah. Kritik pribadi hanya akan membuat orang lain bersikap defensif.
James P.
2
@monadic: Setuju. Enkapsulasi tentu saja merupakan argumen yang valid ketika berhadapan dengan komponen inti, atau objek kompleks, dll., Namun sebagai representasi catatan yang seharusnya dapat dibaca-tulis. array, ini dapat diterima. Lebih lanjut, ini memungkinkan pengecekan tipe yang lebih mudah karena catatan melayang melalui sistem.
Dan Lugg
15
@outis saya harap saya bukan minoritas di sini, tapi saya tidak merasa jawaban harus dinilai berdasarkan keamanan mereka terhadap pengembang baru. Kedengarannya kasar, tapi itu benar. Tujuan dari jawaban pada SO bukan hanya untuk menyediakan kode salin dan rekat, tetapi juga untuk memberikan pemahaman. Bukan tugas penjawab untuk memastikan setiap lubang keamanan atau cacat pola tercakup dalam sebuah contoh, karena mari kita hadapi itu, aplikasi kode yang disalin ke dalamnya secara inheren berbeda dari setiap aplikasi lain yang menggunakan kode yang sama.
Mattygabe
57

Memindahkan aplikasi dari satu basis data ke basis data tidak umum, tetapi cepat atau lambat Anda mungkin menemukan diri Anda mengerjakan proyek lain menggunakan RDBMS yang berbeda. Jika Anda di rumah dengan PDO maka setidaknya akan ada satu hal yang kurang untuk dipelajari pada saat itu.

Selain itu saya menemukan API PDO sedikit lebih intuitif, dan rasanya lebih benar-benar berorientasi objek. mysqli terasa seperti itu hanya API prosedural yang telah diobjekkan, jika Anda tahu apa yang saya maksud. Singkatnya, saya menemukan PDO lebih mudah untuk dikerjakan, tapi itu tentu saja subjektif.

Theo
sumber
25

Saya sudah mulai menggunakan PDO karena dukungan pernyataannya lebih baik, menurut saya. Saya menggunakan lapisan akses data ActiveRecord-esque, dan jauh lebih mudah untuk mengimplementasikan pernyataan yang dihasilkan secara dinamis. Pengikatan parameter MySQLi harus dilakukan dalam satu panggilan fungsi / metode, jadi jika Anda tidak tahu sampai runtime berapa banyak parameter yang ingin Anda ikat, Anda terpaksa menggunakan call_user_func_array()(saya percaya itu nama fungsi yang tepat) untuk memilih . Dan lupakan mengikat hasil dinamis sederhana.

Yang paling penting, saya suka PDO karena ini adalah tingkat abstraksi yang sangat masuk akal. Sangat mudah untuk menggunakannya dalam sistem abstrak sepenuhnya di mana Anda tidak ingin menulis SQL, tetapi juga membuatnya mudah untuk menggunakan jenis sistem permintaan yang lebih dioptimalkan, murni, atau untuk mencampur-dan-mencocokkan keduanya.

Brian Warshaw
sumber
2
Pengikatan hasil dengan pertanyaan dinamis yang dihasilkan adalah mungkin, kami melakukannya di aplikasi kami. Namun itu adalah rasa sakit yang sangat besar.
Pim Jager
17

PDO adalah standar, itulah yang sebagian besar pengembang harapkan untuk digunakan. mysqli pada dasarnya adalah solusi yang dipesan lebih dahulu untuk masalah tertentu, tetapi memiliki semua masalah perpustakaan DBMS-spesifik lainnya. PDO adalah tempat semua kerja keras dan pemikiran cerdas akan pergi.

Dave Gregory
sumber
15

Ada hal lain yang perlu diingat: Untuk saat ini (PHP 5.2) perpustakaan PDO bermasalah . Penuh dengan bug aneh. Sebagai contoh: sebelum menyimpan sebuah PDOStatementvariabel, variabelnya adalah unset()untuk menghindari satu ton bug. Sebagian besar telah diperbaiki dalam PHP 5.3 dan akan dirilis pada awal 2009 di PHP 5.3 yang mungkin akan memiliki banyak bug lainnya. Anda harus fokus menggunakan PDO untuk PHP 6.1 jika Anda ingin rilis yang stabil dan menggunakan PDO untuk PHP 5.3 jika Anda ingin membantu komunitas.

Tom
sumber
2
Saya pikir bahwa keuntungan yang ditawarkan PDO layak dipahami dan mengatasi bug. PHP sendiri penuh dengan bug yang sangat menjengkelkan, beberapa di antaranya bahkan tidak bisa kita atasi secara efisien, namun PHP menawarkan banyak manfaat yang menyebabkan kita menggunakannya alih-alih opsi lain.
Brian Warshaw
11
Uhm, aneh, saya tidak pernah mengalami bug dengan PDO. Dan saya sering menggunakannya.
NikiC
Mysqli juga memiliki bug. Semua perangkat lunak memiliki bug.
Bill Karwin
10

Perbedaan penting lainnya (baik) tentang PDO adalah PDO::quote()metodenya secara otomatis menambahkan tanda kutip, sedangkan mysqli::real_escape_string()(dan sejenisnya) tidak:

PDO :: quote () menempatkan kutipan di sekitar string input (jika diperlukan) dan lolos dari karakter khusus dalam string input, menggunakan gaya kutipan yang sesuai dengan driver yang mendasarinya.

Alix Axel
sumber
8

PDO akan membuatnya jauh lebih mudah untuk mengukur jika situs / aplikasi web Anda benar-benar menjadi seperti yang Anda dapat setiap hari mengatur koneksi Master dan slave untuk mendistribusikan beban di seluruh database, ditambah PHP sedang menuju ke pindah ke PDO sebagai standar.

Info PDO

Menskalakan Aplikasi Web

Dfranc3373
sumber
6

Dalam arti kecepatan eksekusi, MySQLi menang, tetapi kecuali jika Anda memiliki pembungkus yang baik menggunakan MySQLi, fungsinya berurusan dengan pernyataan yang disiapkan sangat buruk.

Masih ada bug di saya, tetapi jika ada yang menginginkannya, ini dia .

Jadi singkatnya, jika Anda mencari kenaikan kecepatan, maka MySQLi; jika Anda ingin kemudahan penggunaan, maka PDO.

Ry-
sumber
2
dalam hal kecepatan, dapatkah Anda memberikan tolok ukur?
Julius F
8
Jonathen Robson telah melakukan perbandingan kecepatan yang layak dari keduanya di jonathanrobson.me/2010/06/mysqli-vs-pdo-benchmarks . Ringkasan: inserts - hampir sama, selects - mysqli ~ 2,5% lebih cepat untuk pernyataan yang tidak disiapkan / ~ 6,7% lebih cepat untuk pernyataan yang disiapkan. Mengingat seberapa kecil penalti kinerja, fitur dan fleksibilitas penggunaan PDOsecara umum lebih besar daripada hit kinerja.
Adam
1
@Adam Terima kasih telah menautkan ke blog saya!
jnrbsn
@ daemonfire300 Ini benar, tidak perlu benchmark. PDO membungkus perpustakaan mysqli. Saya mungkin akan memukul penggemar jika seseorang dapat membuktikan bahwa PDO lebih cepat dari mysqli. :-D
Dyin
@ jnrbsn apakah Anda setuju dengan Adam tentang apa yang dia katakan?
Basit
5

Secara pribadi saya menggunakan PDO, tapi saya pikir itu terutama masalah preferensi.

PDO memiliki beberapa fitur yang membantu melawan injeksi SQL ( pernyataan yang disiapkan ), tetapi jika Anda berhati-hati dengan SQL, Anda juga dapat mencapainya dengan mysqli.

Pindah ke database lain bukan alasan untuk menggunakan PDO. Selama Anda tidak menggunakan "fitur SQL khusus", Anda dapat beralih dari satu DB ke yang lain. Namun begitu Anda menggunakan misalnya "SELECT ... LIMIT 1" Anda tidak dapat pergi ke MS-SQL di mana "SELECT TOP 1 ...". Jadi ini tetap bermasalah.

BlaM
sumber
22
MySQLi sudah menyiapkan pernyataan.
Tower
5

Jawaban yang diedit.

Setelah memiliki pengalaman dengan kedua API ini, saya akan mengatakan bahwa ada 2 fitur level pemblokiran yang membuat mysqli tidak dapat digunakan dengan pernyataan asli yang disiapkan.
Mereka telah disebutkan dalam 2 jawaban yang sangat baik (namun diremehkan):

  1. Mengikat nilai dengan jumlah placeholder yang berubah-ubah
  2. Mengembalikan data sebagai array belaka

(keduanya juga disebutkan dalam jawaban ini )

Untuk beberapa alasan mysqli gagal dengan keduanya.
Saat ini ada beberapa peningkatan untuk yang kedua ( get_result ), tetapi hanya berfungsi pada instalasi mysqlnd, berarti Anda tidak dapat mengandalkan fungsi ini dalam skrip Anda.

Namun itu tidak memiliki nilai demi nilai bahkan hingga hari ini.

Jadi, hanya ada satu pilihan: PDO

Semua alasan lain, seperti

  • bernama placeholder (gula sintaks ini terlalu berlebihan)
  • dukungan basis data yang berbeda (tidak ada yang benar-benar pernah menggunakannya)
  • ambil ke objek (hanya gula sintaks yang tidak berguna)
  • perbedaan kecepatan (tidak ada)

tidak penting secara signifikan.

Pada saat yang sama kedua API ini tidak memiliki beberapa fitur penting yang nyata , seperti

  • placeholder pengidentifikasi
  • placeholder untuk tipe data yang kompleks untuk membuat pengikatan dinamis kurang sulit
  • kode aplikasi yang lebih pendek.

Jadi, untuk memenuhi kebutuhan kehidupan nyata , kita harus membuat perpustakaan abstraksi sendiri, berdasarkan salah satu API ini, menerapkan placeholder yang diuraikan secara manual. Dalam hal ini saya lebih suka mysqli, karena memiliki tingkat abstraksi yang lebih rendah.

Akal Sehat Anda
sumber
Akhirnya seseorang yang tahu dan tidak menyangkal fakta kehidupan ...
Ihsan
4

Dalam skrip patokan saya , setiap metode diuji 10.000 kali dan perbedaan total waktu untuk setiap metode dicetak. Anda harus melakukan ini pada konfigurasi Anda sendiri, saya yakin hasilnya akan bervariasi!

Ini hasil saya:

  • "Lebih SELECT NULL" -> PGO()cepat dengan ~ 0,35 detik
  • "Lebih SHOW TABLE STATUS" -> mysqli()cepat ~ 2,3 detik
  • " SELECT * FROM users" -> mysqli()lebih cepat ~ 33 detik

Catatan: dengan menggunakan -> fetch_row () untuk mysqli, nama kolom tidak ditambahkan ke array, saya tidak menemukan cara untuk melakukannya di PGO. Tetapi bahkan jika saya menggunakan -> fetch_array (), mysqli sedikit lebih lambat tetapi masih lebih cepat dari PGO (kecuali untuk SELECT NULL).

Dobb
sumber
17
Apa itu PGO? Dan lebih cepat 33 detik ?! Saya merasa sangat sulit untuk percaya ...
Alix Axel
3

Satu hal PDO memiliki bahwa MySQLi tidak begitu saya sukai adalah kemampuan PDO untuk mengembalikan hasil sebagai objek dari tipe kelas tertentu (misalnya $pdo->fetchObject('MyClass')). MySQLi fetch_object()hanya akan mengembalikan stdClassobjek.

Daging Tanpa Label
sumber
19
Sebenarnya, Anda dapat menentukan kelas secara manual: "object mysqli_result :: fetch_object ([string $ class_name [, array $ params]])". stdClass hanya digunakan jika Anda tidak menentukan apa pun.
Andrioid
-4

Ada satu hal yang perlu diingat.

Mysqli tidak mendukung fungsi fetch_assoc () yang akan mengembalikan kolom dengan kunci yang mewakili nama kolom. Tentu saja mungkin untuk menulis fungsi Anda sendiri untuk melakukan itu, itu bahkan tidak terlalu lama, tetapi saya sudah melakukannya benar benar kesulitan menulisnya (untuk orang yang tidak percaya: jika itu tampak mudah bagi Anda, cobalah beberapa waktu sendiri dan jangan t cheat :))

mikrofon
sumber
4
Apakah Anda mencoba manual? php.net/manual/en/mysqli-result.fetch-assoc.php
Hingga
2
Sudah menerapkan lebih lama, tapi ya saya memeriksa manual. Apakah ini berhasil dengan pernyataan yang sudah disiapkan? Saya ragu ...
mike
2
Sebenarnya, ia memiliki dukungan parsial yang aneh. Anda dapat mengambil array dalam kueri reguler tetapi tidak dalam kueri parametrized: -!
Álvaro González
1
Mengapa tidak menghapus jawaban yang jelas salah?
Majid Fouladpour
2
@MajidFouladpour - Jawabannya jelas tidak salah . Itu hanya melewatkan beberapa konteks. Mysqli tidak sepenuhnya mendukung pengambilan array asosiatif.
Álvaro González