Untuk menjawab kekhawatiran Anda:
MySQL> = 5.1.17 (atau> = 5.1.21 untuk pernyataan PREPARE
dan EXECUTE
) dapat menggunakan pernyataan yang disiapkan di cache kueri . Jadi versi MySQL + PHP Anda dapat menggunakan pernyataan yang disiapkan dengan cache kueri. Namun, perhatikan peringatan untuk hasil kueri caching di dokumentasi MySQL. Ada banyak jenis kueri yang tidak dapat disimpan dalam cache atau tidak berguna meskipun telah disimpan dalam cache. Menurut pengalaman saya, cache kueri seringkali bukan merupakan kemenangan yang sangat besar. Query dan skema membutuhkan konstruksi khusus untuk memaksimalkan penggunaan cache. Seringkali cache tingkat aplikasi akhirnya diperlukan dalam jangka panjang.
Persiapan asli tidak membuat perbedaan apa pun untuk keamanan. Pernyataan pseudo-prepared masih akan lolos dari nilai parameter kueri, itu hanya akan dilakukan di perpustakaan PDO dengan string alih-alih di server MySQL menggunakan protokol biner. Dengan kata lain, kode PDO yang sama akan sama-sama rentan (atau tidak rentan) terhadap serangan injeksi apa pun EMULATE_PREPARES
setelan Anda . Satu-satunya perbedaan adalah di mana penggantian parameter terjadi - dengan EMULATE_PREPARES
, itu terjadi di perpustakaan PDO; tanpaEMULATE_PREPARES
, ini terjadi di server MySQL.
Tanpa EMULATE_PREPARES
Anda mungkin mendapatkan kesalahan sintaks pada waktu persiapan daripada pada waktu eksekusi; dengan EMULATE_PREPARES
Anda hanya akan mendapatkan kesalahan sintaks pada waktu eksekusi karena PDO tidak memiliki permintaan untuk diberikan ke MySQL sampai waktu eksekusi. Perhatikan bahwa ini memengaruhi kode yang akan Anda tulis ! Terutama jika Anda menggunakan PDO::ERRMODE_EXCEPTION
!
Pertimbangan tambahan:
- Ada biaya tetap untuk
prepare()
(menggunakan pernyataan yang disiapkan asli), jadi prepare();execute()
dengan pernyataan yang disiapkan asli mungkin sedikit lebih lambat daripada mengeluarkan kueri tekstual biasa menggunakan pernyataan siap yang diemulasi. Pada banyak sistem database, rencana kueri untuk a di prepare()
-cache juga dan dapat dibagikan dengan banyak koneksi, tetapi menurut saya MySQL tidak melakukan ini. Jadi, jika Anda tidak menggunakan kembali objek pernyataan yang Anda siapkan untuk beberapa kueri, eksekusi Anda secara keseluruhan mungkin lebih lambat.
Sebagai rekomendasi akhir , saya pikir dengan versi MySQL + PHP yang lebih lama, Anda harus meniru pernyataan yang sudah disiapkan, tetapi dengan versi terbaru Anda, Anda harus mematikan emulasi.
Setelah menulis beberapa aplikasi yang menggunakan PDO, saya telah membuat fungsi koneksi PDO yang menurut saya merupakan pengaturan terbaik. Anda mungkin harus menggunakan sesuatu seperti ini atau menyesuaikan pengaturan pilihan Anda:
/**
* Return PDO handle for a MySQL connection using supplied settings
*
* Tries to do the right thing with different php and mysql versions.
*
* @param array $settings with keys: host, port, unix_socket, dbname, charset, user, pass. Some may be omitted or NULL.
* @return PDO
* @author Francis Avila
*/
function connect_PDO($settings)
{
$emulate_prepares_below_version = '5.1.17';
$dsndefaults = array_fill_keys(array('host', 'port', 'unix_socket', 'dbname', 'charset'), null);
$dsnarr = array_intersect_key($settings, $dsndefaults);
$dsnarr += $dsndefaults;
// connection options I like
$options = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
);
// connection charset handling for old php versions
if ($dsnarr['charset'] and version_compare(PHP_VERSION, '5.3.6', '<')) {
$options[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES '.$dsnarr['charset'];
}
$dsnpairs = array();
foreach ($dsnarr as $k => $v) {
if ($v===null) continue;
$dsnpairs[] = "{$k}={$v}";
}
$dsn = 'mysql:'.implode(';', $dsnpairs);
$dbh = new PDO($dsn, $settings['user'], $settings['pass'], $options);
// Set prepared statement emulation depending on server version
$serverversion = $dbh->getAttribute(PDO::ATTR_SERVER_VERSION);
$emulate_prepares = (version_compare($serverversion, $emulate_prepares_below_version, '<'));
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, $emulate_prepares);
return $dbh;
}