Perilaku tersebut dapat direproduksi dengan PHP saat ini (5.6.13), dan kueri bahkan tidak dikirim ke server.
Kasus Anda dijelaskan dalam dokumen sebagai:
0 nilai diharapkan, 1 nilai diberikan, dan pernyataan gagal, false
dikembalikan. Sejauh ini, berfungsi seperti yang didokumentasikan.
Anda mungkin berpendapat bahwa "terjadi kesalahan " akan menyiratkan bahwa ketika ERRMODE_EXCEPTION
aktif, pengecualian akan dilemparkan. Itu adalah argumen, tetapi tidak jelas bahwa pengembang PDO akan menyetujuinya.
Pembaruan:
Mengapa SQLCode
tidak disetel?
Melihat kode sumber PDO, khususnya static PHP_METHOD(PDOStatement, execute)
yang menangani PDO::execute(), Anda dapat melihat bahwa semua kesalahan ditangani oleh makro:PDO_HANDLE_STMT_ERR()
#define PDO_HANDLE_STMT_ERR() if (strcmp(stmt->error_code, PDO_ERR_NONE)) { pdo_handle_error(stmt->dbh, stmt TSRMLS_CC); }
Intinya adalah, ketika melewati parameter terikat ketika PDO tidak mengharapkan apa pun, kueri tidak pernah sampai ke mesin SQL, sehingga mesin SQL tidak pernah memiliki kesempatan untuk melaporkan kesalahan yang disertai dengan SQLSTATE
PDO sendiri tidak membuat SQLSTATE
palsu sendiri, setidaknya tidak dalam kasus itu, jadistmt->error_code
tetap di PDO_ERR_NONE
yaitu "00000"
.
Dapat dimengerti bahwa Anda lebih suka memunculkan pengecualian, tetapi Anda harus menyarankannya ke https://bugs.php. bersih
Apakah sama dengan MySQL ?
Ya, root behaviornya sama kecuali dengan driver MySQL, prepare
dikirim segera ke mesin SQL jadi jika salah karena kolom yang buruk, gagal sebelumnya dan dengan kesalahan SQL nyata. Di sisi lain, driver PgSQL memiliki implementasi berbeda yang membuatnya menunda prepare
sisi server . Perilaku khusus ini dibahas secara mendetail di Driver PHP Postgres PDO tidak mendukung pernyataan yang disiapkan?
Bagaimanapun, ini adalah kasus dengan MySQL yang menunjukkan penjelasan saya, yaitu:
- kueri mengharapkan 0 parameter, 1 diberikan
$stmt->execute
mengembalikan false- tidak ada pengecualian yang diangkat
- PDO::errorCode adalah
00000
Kode:
$link = new PDO('mysql:dbname=' . $name . ';host=' . $host, $user, $password);
$link->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$link->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
try {
$stmt = $link->prepare("SELECT 1");
$rc=$stmt->execute(array(1));
if ($rc===false)
echo "query failed, errorCode=", $link->errorCode(), "\n";
else
echo "query succeeded, errorCode=", $link->errorCode(), "\n";
}
catch (PDOException $e) {
print "A PDOException has occurred";
print $e->getMessage();
}
Hasil:
Apa yang terjadi di bawah tenda adalah bahwa prepare
dikirim ke server dan berhasil, tetapi execute
langkah dibatalkan oleh PDO karena ketidakcocokan parameter.
Berikut adalah kasus yang berbeda dalam kenyataan bahwa kueri merujuk ke kolom yang tidak ada. Saya menambahkan cetakan untuk menunjukkan bahwa $stmt->execute
bahkan tidak dipanggil, karena pengecualian dimunculkan oleh $stmt->prepare
Kode:
$link = new PDO('mysql:dbname=' . $name . ';host=' . $host, $user, $password);
$link->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$link->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
try {
$stmt = $link->prepare("SELECT nonexisting");
echo "Executing query\n";
$rc=$stmt->execute(array(1));
if ($rc===false)
echo "query failed, errorCode=", $link->errorCode(), "\n";
else
echo "query succeeded, errorCode=", $link->errorCode(), "\n";
}
catch (PDOException $e) {
print "A PDOException has occurred";
print $e->getMessage();
}
Hasil:
Perhatikan bagaimana langkah "Melaksanakan kueri" tidak pernah terjadi, karena ini adalah prepare
yang gagal, sisi server.
Kesimpulan
-
ketika kueri dikirim ke server, baik itu di prepare() atau execute(), dan serverlah yang menghasilkan kesalahan, maka kita dapat mengharapkan PDOException untuk dimunculkan.
-
ketika kueri tidak dikirim ke server untuk langkah eksekusi, maka eksekusi PDO() bisa gagal (mengembalikan false) tetapi tidak ada pengecualian yang dilemparkan dan
errorCode()
tetap di00000