Untuk menjawab kekhawatiran Anda:
-
MySQL>=5.1.17 (atau>=5.1.21 untuk
PREPARE
danEXECUTE
pernyataan) dapat menggunakan pernyataan yang disiapkan dalam cache kueri . Jadi versi MySQL+PHP Anda dapat menggunakan pernyataan yang disiapkan dengan cache kueri. Namun, perhatikan baik-baik peringatan untuk caching hasil kueri dalam dokumentasi MySQL. Ada banyak jenis kueri yang tidak dapat di-cache atau yang tidak berguna meskipun di-cache. Dalam pengalaman saya, cache kueri seringkali bukan merupakan kemenangan yang sangat besar. Kueri dan skema memerlukan konstruksi khusus untuk memaksimalkan penggunaan cache. Seringkali cache tingkat aplikasi tetap diperlukan dalam jangka panjang. -
Persiapan asli tidak membuat perbedaan untuk keamanan. Pernyataan yang disiapkan semu masih akan lolos dari nilai parameter kueri, itu hanya akan dilakukan di perpustakaan PDO dengan string, bukan di server MySQL menggunakan protokol biner. Dengan kata lain, kode PDO yang sama akan sama-sama rentan (atau tidak rentan) terhadap serangan injeksi terlepas dari
EMULATE_PREPARES
Anda. pengaturan. Satu-satunya perbedaan adalah di mana penggantian parameter terjadi--denganEMULATE_PREPARES
, itu terjadi di perpustakaan PDO; tanpaEMULATE_PREPARES
, itu terjadi di server MySQL. -
Tanpa
EMULATE_PREPARES
anda mungkin mendapatkan kesalahan sintaks pada waktu persiapan daripada pada waktu eksekusi; denganEMULATE_PREPARES
Anda hanya akan mendapatkan kesalahan sintaks pada waktu eksekusi karena PDO tidak memiliki kueri untuk diberikan ke MySQL hingga waktu eksekusi. Perhatikan bahwa ini memengaruhi kode yang akan Anda tulis ! Terutama jika Anda menggunakanPDO::ERRMODE_EXCEPTION
!
Pertimbangan tambahan:
- Ada biaya tetap untuk
prepare()
(menggunakan pernyataan asli yang disiapkan), jadiprepare();execute()
dengan pernyataan yang disiapkan asli mungkin sedikit lebih lambat daripada mengeluarkan kueri tekstual biasa menggunakan pernyataan yang disiapkan yang ditiru. Pada banyak sistem database, rencana kueri untukprepare()
di-cache juga dan dapat dibagikan dengan banyak koneksi, tetapi saya tidak berpikir MySQL melakukan ini. Jadi, jika Anda tidak menggunakan kembali objek pernyataan yang telah disiapkan untuk beberapa kueri, keseluruhan eksekusi Anda mungkin akan lebih lambat.
Sebagai rekomendasi akhir , saya pikir dengan versi MySQL+PHP yang lebih lama, Anda harus meniru pernyataan yang telah disiapkan, tetapi dengan versi terbaru Anda, Anda harus menonaktifkan emulasi.
Setelah menulis beberapa aplikasi yang menggunakan PDO, saya telah membuat fungsi koneksi PDO yang menurut saya adalah pengaturan terbaik. Anda mungkin harus menggunakan sesuatu seperti ini atau mengubah 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;
}