Bạn đúng rằng trường hợp đầu tiên là không an toàn. Tuy nhiên, điều quan trọng là phải hiểu rằng việc chuẩn bị một câu lệnh chỉ có giá trị nếu bạn đang sử dụng dữ liệu biến và / hoặc thực hiện lặp lại cùng một truy vấn. Nếu bạn đang thực thi các câu lệnh đơn giản không có biến , bạn chỉ có thể làm điều này:
$sql = "SELECT * from myTable WHERE this_column IS NOT NULL";
$result = $conn->query($sql);
Và kết thúc với một PDOStatement
đối tượng để làm việc, giống như khi bạn sử dụng PDO::exec()
.
Đối với trường hợp thứ hai của bạn, một lần nữa, bạn phần lớn chính xác. Điều gì đang xảy ra là biến được chuyển đến cơ sở dữ liệu được thoát và được trích dẫn (trừ khi bạn chỉ định khác với đối số thứ ba cho PDOStatement::bindParam()
, nó được gửi dưới dạng một chuỗi, điều này tốt cho hầu hết các trường hợp.) Vì vậy, truy vấn sẽ không "thất bại" nếu dữ liệu xấu được gửi. Nó hoạt động chính xác như thể bạn đã chuyển một số hợp lệ không tồn tại dưới dạng ID trong cơ sở dữ liệu. Tất nhiên, có một số các trường hợp cạnh
nơi bạn vẫn dễ bị tấn công ngay cả với một tuyên bố được chuẩn bị chính xác.
Ngoài ra, để làm cho cuộc sống dễ dàng hơn, bạn có thể sử dụng các câu lệnh chuẩn bị sẵn như sau, để thực hiện ràng buộc ngầm:
$sql = "SELECT * FROM myTable WHERE id = :id";
$stmt = $conn->prepare($sql);
$stmt->execute([":id"=>$id]);
Hoặc thậm chí như thế này, với các tham số chưa được đặt tên:
$sql = "SELECT * FROM myTable WHERE id = ?";
$stmt = $conn->prepare($sql);
$stmt->execute([$id]);
Đương nhiên, hầu hết điều này đã được giải thích trong các nhận xét khi tôi đang gõ câu trả lời!