Hành vi đó có thể tái tạo với PHP hiện tại (5.6.13) và truy vấn thậm chí không được gửi đến máy chủ.
Trường hợp của bạn được mô tả trong tài liệu như:
Giá trị 0 được mong đợi, 1 giá trị được đưa ra và câu lệnh không thành công, false
được trả lại. Cho đến nay, hoạt động như được ghi lại.
Bạn có thể lập luận rằng " lỗi được tạo ra "sẽ ngụ ý rằng khi ERRMODE_EXCEPTION
đang bật, một ngoại lệ sẽ được ném ra. Đó là một lập luận, nhưng không rõ ràng là các nhà phát triển PDO sẽ đồng ý với nó.
Cập nhật:
Tại sao lại là SQLCode
chưa đặt?
Nhìn vào mã nguồn PDO, cụ thể là static PHP_METHOD(PDOStatement, execute)
xử lý PDO ::execute (), bạn có thể thấy rằng tất cả các lỗi đều được xử lý bởi macro: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); }
Vấn đề ở đây là, khi truyền một tham số bị ràng buộc khi PDO không mong đợi, truy vấn sẽ không bao giờ đến được với công cụ SQL, do đó, công cụ SQL không bao giờ có cơ hội báo cáo lỗi kèm theo SQLSTATE
Bản thân PDO không tạo SQLSTATE
giả riêng nó, ít nhất là không trong trường hợp đó, vì vậy stmt->error_code
vẫn ở PDO_ERR_NONE
là "00000"
.
Có thể hiểu rằng bạn muốn một ngoại lệ được nêu ra, nhưng sau đó bạn nên đề xuất điều đó với https://bugs.php. net
Nó có giống với MySQL không?
Có, hành vi gốc giống nhau ngoại trừ với trình điều khiển MySQL, prepare
được gửi ngay lập tức đến công cụ SQL, vì vậy nếu nó không chính xác do một cột không hợp lệ, nó sẽ bị lỗi sớm hơn và với một lỗi SQL thực sự. Mặt khác, trình điều khiển PgSQL có một triển khai khác khiến nó trì hoãn prepare
phía máy chủ . Hành vi cụ thể này được thảo luận chi tiết tại Trình điều khiển PHP Postgres PDO không hỗ trợ câu lệnh đã soạn sẵn?
Dù sao, đây là một trường hợp với MySQL minh chứng cho lời giải thích của tôi, đó là:
- truy vấn yêu cầu tham số 0, 1 được cung cấp
-
$stmt->execute
trả về false - không có ngoại lệ nào được nêu ra
- PDO ::errorCode là
00000
Mã:
$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();
}
Kết quả:
Điều gì xảy ra ẩn là prepare
được gửi đến máy chủ và thành công, nhưng execute
PDO đã hủy bước do thông số không khớp.
Đây là một trường hợp khác với thực tế là truy vấn đề cập đến một cột không tồn tại. Tôi đang thêm một bản in để cho thấy rằng $stmt->execute
thậm chí không được gọi, vì ngoại lệ được nêu ra bởi $stmt->prepare
Mã:
$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();
}
Kết quả:
Lưu ý rằng bước "Thực thi truy vấn" không bao giờ xảy ra như thế nào, vì đó là bước prepare
không thành công, phía máy chủ.
Kết luận
-
khi truy vấn được gửi đến máy chủ, có thể là ở chế độ chuẩn bị () hoặc thực thi () và chính máy chủ tạo ra lỗi, khi đó chúng ta có thể mong đợi một ngoại lệ PDOException được đưa ra.
-
khi truy vấn không được gửi đến máy chủ cho một bước thực thi, thì PDO execute () có thể không thành công (trả về false) nhưng không có ngoại lệ nào được đưa ra và
errorCode()
vẫn ở00000