Các quy tắc thêm một biến PHP bên trong bất kỳ câu lệnh MySQL nào rất rõ ràng và đơn giản:
- Bất kỳ biến nào đại diện cho một ký tự dữ liệu SQL , (hoặc, nói một cách đơn giản - một chuỗi SQL hoặc một số) PHẢI được thêm vào thông qua một câu lệnh đã chuẩn bị. Không có ngoại lệ.
- Bất kỳ phần truy vấn nào khác, chẳng hạn như từ khóa SQL, bảng hoặc tên trường hoặc toán tử - phải được lọc qua danh sách trắng .
Vì vậy, vì ví dụ của bạn chỉ liên quan đến các ký tự dữ liệu, nên tất cả các biến phải được thêm vào thông qua trình giữ chỗ (còn được gọi là tham số). Để làm như vậy:
- Trong câu lệnh SQL của bạn, hãy thay thế tất cả các biến bằng trình giữ chỗ
- chuẩn bị truy vấn kết quả
- ràng buộc biến cho trình giữ chỗ
- thực hiện truy vấn
Và đây là cách thực hiện với tất cả các trình điều khiển cơ sở dữ liệu PHP phổ biến:
Thêm ký tự dữ liệu bằng cách sử dụng mysql ext
Trình điều khiển như vậy không tồn tại .
Thêm ký tự dữ liệu bằng mysqli
$type = 'testing';
$reporter = "John O'Hara";
$query = "INSERT INTO contents (type, reporter, description)
VALUES(?, ?, 'whatever')";
$stmt = $mysqli->prepare($query);
$stmt->bind_param("ss", $type, $reporter);
$stmt->execute();
Mã hơi phức tạp nhưng bạn có thể tìm thấy giải thích chi tiết về tất cả các toán tử này trong bài viết của tôi, Cách chạy một CHÈN truy vấn bằng Mysqli , cũng như một giải pháp giúp giảm bớt quá trình một cách đáng kể.
Đối với truy vấn CHỌN, bạn sẽ chỉ cần thêm một lệnh gọi tới get_result()
phương pháp lấy mysqli_result
quen thuộc từ đó bạn có thể tìm nạp dữ liệu theo cách thông thường:
$reporter = "John O'Hara";
$stmt = $mysqli->prepare("SELECT * FROM users WHERE name=?");
$stmt->bind_param("s", $reporter);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc(); // or while (...)
Thêm ký tự dữ liệu bằng PDO
$type = 'testing';
$reporter = "John O'Hara";
$query = "INSERT INTO contents (type, reporter, description)
VALUES(?, ?, 'whatever')";
$stmt = $pdo->prepare($query);
$stmt->execute([$type, $reporter]);
Trong PDO, chúng ta có thể kết hợp các phần ràng buộc và thực thi, điều này rất thuận tiện. PDO cũng hỗ trợ các trình giữ chỗ được đặt tên mà một số thấy rất tiện lợi.
Thêm từ khóa hoặc số nhận dạng
Đôi khi chúng ta phải thêm một biến đại diện cho một phần khác của truy vấn, chẳng hạn như từ khóa hoặc số nhận dạng (cơ sở dữ liệu, bảng hoặc tên trường). Đó là một trường hợp hiếm nhưng tốt hơn hết là bạn nên chuẩn bị.
Trong trường hợp này, biến của bạn phải được kiểm tra dựa trên danh sách các giá trị rõ ràng được viết bằng kịch bản của bạn. Điều này được giải thích trong bài viết khác của tôi, Thêm tên trường trong mệnh đề ORDER BY dựa trên lựa chọn của người dùng :
Thật không may, PDO không có trình giữ chỗ cho số nhận dạng (tên bảng và trường), do đó nhà phát triển phải lọc chúng theo cách thủ công. Bộ lọc như vậy thường được gọi là "danh sách trắng" (nơi chúng tôi chỉ liệt kê các giá trị được phép) thay vì "danh sách đen" nơi chúng tôi liệt kê các giá trị không được phép.
Vì vậy, chúng tôi phải liệt kê rõ ràng tất cả các biến thể có thể có trong mã PHP và sau đó chọn từ chúng.
Đây là một ví dụ:
$orderby = $_GET['orderby'] ?: "name"; // set the default value
$allowed = ["name","price","qty"]; // the white list of allowed field names
$key = array_search($orderby, $allowed, true); // see if we have such a name
if ($key === false) {
throw new InvalidArgumentException("Invalid field name");
}
Chính xác thì cách tiếp cận tương tự nên được sử dụng để định hướng,
$direction = $_GET['direction'] ?: "ASC";
$allowed = ["ASC","DESC"];
$key = array_search($direction, $allowed, true);
if ($key === false) {
throw new InvalidArgumentException("Invalid ORDER BY direction");
}
Sau mã như vậy, cả $direction
và $orderby
Các biến có thể được đặt một cách an toàn trong truy vấn SQL, vì chúng bằng một trong các biến thể được phép hoặc sẽ có lỗi xảy ra.
Điều cuối cùng cần đề cập về mã định danh, chúng cũng phải được định dạng theo cú pháp cơ sở dữ liệu cụ thể. Đối với MySQL, nó phải là backtick
các ký tự xung quanh mã định danh. Vì vậy, chuỗi truy vấn cuối cùng cho đơn đặt hàng của chúng tôi theo ví dụ sẽ là
$query = "SELECT * FROM `table` ORDER BY `$orderby` $direction";