Hướng dẫn what is the advantage of prepared statement in php? - lợi thế của câu lệnh soạn sẵn trong php là gì?

Thoát khỏi các ký tự xấu vẫn cần thiết, nhưng thư viện thực hiện nó tự động cho tất cả các tham số bạn liên kết. Nó chỉ thuận tiện hơn một chút và ngăn người lập trình quên quên làm vệ sinh một giá trị.

Tuy nhiên, lưu ý rằng tính tự động này được giới hạn trong các tham số!

Truy vấn sau đây là an toàn, bởi vì bind_param() chăm sóc việc trốn thoát:

$code = $_GET["code"];
$name= $_GET["name"];
$percentage= $_GET["percentage"];

$stmt = $mysqli->prepare("INSERT INTO items VALUES (?, ?, ?)");
$stmt->bind_param('iss', code, $name, $percentage);
$stmt->execute();

Truy vấn sau đây không an toàn, bởi vì bất cứ điều gì bạn đặt trực tiếp vào truy vấn sẽ không được thoát tự động:unsafe, because anything you put directly into the query will not be escaped automatically:

$tablename = $_GET["prefix"]."_items";  
$code = $_GET["code"];
$name= $_GET["name"];
$percentage= $_GET["percentage"];

                                    ---- UNSAFE! ----
$stmt = $mysqli->prepare("INSERT INTO `$tablename` VALUES (?, ?, ?)");
$stmt->bind_param('iss', $code, $name, $percentage);
$stmt->execute();

Điều đó nói rằng, người ta không nên sử dụng các tên bảng động như được hiển thị trong ví dụ này. Nhưng điểm đứng: Hãy cẩn thận, ngay cả với các truy vấn được tham số!Be careful, even with parametrized queries!

Nhược điểm duy nhất tôi có thể nghĩ đến là bạn không thể nhìn thấy truy vấn cuối cùng nữa để gỡ lỗi (vì nó chỉ được lắp ráp ở phía máy chủ).


Các tuyên bố đã chuẩn bị rất hữu ích chống lại SQL tiêm.


Các câu lệnh được chuẩn bị và các tham số ràng buộc

Một câu lệnh đã chuẩn bị là một tính năng được sử dụng để thực hiện các câu lệnh SQL (hoặc tương tự) giống nhau với hiệu quả cao.

Các tuyên bố chuẩn bị về cơ bản hoạt động như thế này:

  1. Chuẩn bị: Một mẫu câu lệnh SQL được tạo và gửi đến cơ sở dữ liệu. Một số giá trị nhất định không được xác định, được gọi là tham số (được dán nhãn "?"). Ví dụ: Chèn vào các giá trị MyGuests (?,?,?)
  2. Cơ sở dữ liệu phân tích cú pháp, biên dịch và thực hiện tối ưu hóa truy vấn trên mẫu câu lệnh SQL và lưu trữ kết quả mà không cần thực hiện nó
  3. Thực thi: Sau đó, ứng dụng liên kết các giá trị với các tham số và cơ sở dữ liệu thực thi câu lệnh. Ứng dụng có thể thực thi câu lệnh nhiều lần như nó muốn với các giá trị khác nhau

So với việc thực thi các câu lệnh SQL trực tiếp, các câu lệnh được chuẩn bị có ba lợi thế chính:

  • Các câu lệnh đã chuẩn bị giảm thời gian phân tích cú pháp khi việc chuẩn bị trên truy vấn chỉ được thực hiện một lần (mặc dù câu lệnh được thực thi nhiều lần)
  • Các tham số ràng buộc giảm thiểu băng thông cho máy chủ vì bạn chỉ cần gửi các tham số mỗi lần chứ không phải toàn bộ truy vấn
  • Các câu lệnh được chuẩn bị rất hữu ích đối với tiêm SQL, bởi vì các giá trị tham số, được truyền sau đó bằng cách sử dụng một giao thức khác, không cần phải thoát ra một cách chính xác. Nếu mẫu câu lệnh gốc không có nguồn gốc từ đầu vào bên ngoài, thì SQL tiêm không thể xảy ra.

Các tuyên bố đã chuẩn bị trong mysqli

Ví dụ sau sử dụng các câu lệnh đã chuẩn bị và tham số ràng buộc trong MySQLI:

Ví dụ (mysqli với các câu lệnh đã chuẩn bị)

$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";

thử {& nbsp; $ Conn = new PDO ("mysql: host = $ servername; dbname = $ dbname", $ username, $ password); & nbsp; // Đặt chế độ lỗi PDO thành Exception & NBSP; $ Conn-> setAttribution (pdo :: attr_errmode, pdo :: errmode_exception);
$conn = new mysqli($servername, $username, $password, $dbname);

& nbsp; // Chuẩn bị các tham số SQL và liên kết & nbsp; $ STMT = $ Conn-> Chuẩn bị ("Chèn vào MyGuests (FirstName, LastName, Email) & NBSP; Giá trị (: FirstName,: LastName,: Email)"); & nbsp; $ stmt-> bindparam (': firstName', $ firstName); & nbsp; $ stmt-> bindParam (': lastName', $ lastName); & nbsp; $ stmt-> bindparam (': email', $ email);
if ($conn->connect_error) {
  die("Connection failed: " . $conn->connect_error);
}

& nbsp; & nbsp; // chèn một hàng & nbsp; & nbsp; $ firstName = "john"; & nbsp; & nbsp; $ STMT-> EXECUTE ();
$stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $firstname, $lastname, $email);

& nbsp; & nbsp; // chèn một hàng khác & nbsp; & nbsp; $ STMT-> EXECUTE ();
$firstname = "John";
$lastname = "Doe";
$email = "";
$stmt->execute();

& nbsp; // chèn một hàng khác & nbsp; $ FirstName = "Julie"; & nbsp; $ lastName = "dooley"; & nbsp; $ email = ""; & nbsp; $ STMT-> EXECUTE ();
$lastname = "Moe";
$email = "";
$stmt->execute();

& nbsp; echo "bản ghi mới được tạo thành công";} Catch (pDoException $ e) {& nbsp; Echo "Lỗi:". $ e-> getMessage ();} $ Conn = null; ?>
$lastname = "Dooley";
$email = "";
$stmt->execute();

Tại sao chúng ta sử dụng tuyên bố đã chuẩn bị trong PHP?

Các câu lệnh đã chuẩn bị giảm thời gian phân tích cú pháp khi việc chuẩn bị trên truy vấn chỉ được thực hiện một lần (mặc dù câu lệnh được thực thi nhiều lần) Các tham số ràng buộc giảm thiểu băng thông đến máy chủ vì bạn chỉ cần gửi các tham số mỗi lần và không phải toàn bộ truy vấn.
$conn->close();
?>


Lợi thế và nhược điểm của việc sử dụng tuyên bố đã chuẩn bị qua tuyên bố là gì?

Bằng cách tránh nhiều biên dịch và thực hiện các câu lệnh, các câu lệnh được chuẩn bị thực hiện nhanh hơn. Sử dụng các câu lệnh đã chuẩn bị, chúng ta có thể chèn các giá trị vào các kiểu dữ liệu nâng cao như blob, Clob, đối tượng dễ dàng với sự trợ giúp của các phương thức setter được cung cấp bởi giao diện PreparedStatement.

Các tuyên bố đã chuẩn bị rất hữu ích chống lại SQL tiêm.

Các câu lệnh được chuẩn bị và các tham số ràng buộc

$ STMT-> BIND_PARAM ("SSS", $ FirstName, $ LastName, $ Email);

Hàm này liên kết các tham số với truy vấn SQL và cho biết cơ sở dữ liệu các tham số là gì. Đối số "SSS" liệt kê các loại dữ liệu mà các tham số là. Nhân vật S nói với MySQL rằng tham số là một chuỗi.

Đối số có thể là một trong bốn loại:

  • Tôi - Số nguyên
  • D - gấp đôi
  • S - Chuỗi
  • B - Blob

Chúng ta phải có một trong số này cho mỗi tham số.

Bằng cách nói với MySQL loại dữ liệu nào sẽ xảy ra, chúng tôi giảm thiểu nguy cơ tiêm SQL.

Lưu ý: Nếu chúng tôi muốn chèn bất kỳ dữ liệu nào từ các nguồn bên ngoài (như đầu vào của người dùng), điều rất quan trọng là dữ liệu được vệ sinh và xác thực. If we want to insert any data from external sources (like user input), it is very important that the data is sanitized and validated.



Báo cáo chuẩn bị trong PDO

Ví dụ sau sử dụng các câu lệnh đã chuẩn bị và tham số ràng buộc trong PDO:

Ví dụ (PDO với các câu lệnh đã chuẩn bị)

$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDBPDO";

thử {& nbsp; $ Conn = new PDO ("mysql: host = $ servername; dbname = $ dbname", $ username, $ password); & nbsp; // Đặt chế độ lỗi PDO thành Exception & NBSP; $ Conn-> setAttribution (pdo :: attr_errmode, pdo :: errmode_exception);
  $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
  // set the PDO error mode to exception
  $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

& nbsp; // Chuẩn bị các tham số SQL và liên kết & nbsp; $ STMT = $ Conn-> Chuẩn bị ("Chèn vào MyGuests (FirstName, LastName, Email) & NBSP; Giá trị (: FirstName,: LastName,: Email)"); & nbsp; $ stmt-> bindparam (': firstName', $ firstName); & nbsp; $ stmt-> bindParam (': lastName', $ lastName); & nbsp; $ stmt-> bindparam (': email', $ email);
  $stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email)
  VALUES (:firstname, :lastname, :email)");
  $stmt->bindParam(':firstname', $firstname);
  $stmt->bindParam(':lastname', $lastname);
  $stmt->bindParam(':email', $email);

& nbsp; & nbsp; // chèn một hàng & nbsp; & nbsp; $ firstName = "john"; & nbsp; & nbsp; $ STMT-> EXECUTE ();
  $firstname = "John";
  $lastname = "Doe";
  $email = "";
  $stmt->execute();

& nbsp; & nbsp; // chèn một hàng khác & nbsp; & nbsp; $ STMT-> EXECUTE ();
  $firstname = "Mary";
  $lastname = "Moe";
  $email = "";
  $stmt->execute();

& nbsp; // chèn một hàng khác & nbsp; $ FirstName = "Julie"; & nbsp; $ lastName = "dooley"; & nbsp; $ email = ""; & nbsp; $ STMT-> EXECUTE ();
  $firstname = "Julie";
  $lastname = "Dooley";
  $email = "";
  $stmt->execute();

& nbsp; echo "bản ghi mới được tạo thành công";} Catch (pDoException $ e) {& nbsp; Echo "Lỗi:". $ e-> getMessage ();} $ Conn = null; ?>
} catch(PDOException $e) {
  echo "Error: " . $e->getMessage();
}
$conn = null;
?>




Tại sao chúng ta sử dụng tuyên bố đã chuẩn bị trong PHP?

Các câu lệnh đã chuẩn bị giảm thời gian phân tích cú pháp khi việc chuẩn bị trên truy vấn chỉ được thực hiện một lần (mặc dù câu lệnh được thực thi nhiều lần) Các tham số ràng buộc giảm thiểu băng thông đến máy chủ vì bạn chỉ cần gửi các tham số mỗi lần và không phải toàn bộ truy vấn.reduce parsing time as the preparation on the query is done only once (although the statement is executed multiple times) Bound parameters minimize bandwidth to the server as you need send only the parameters each time, and not the whole query.

Lợi thế và nhược điểm của việc sử dụng tuyên bố đã chuẩn bị qua tuyên bố là gì?

Bằng cách tránh nhiều biên dịch và thực hiện các câu lệnh, các câu lệnh được chuẩn bị thực hiện nhanh hơn.Sử dụng các câu lệnh đã chuẩn bị, chúng ta có thể chèn các giá trị vào các kiểu dữ liệu nâng cao như blob, Clob, đối tượng dễ dàng với sự trợ giúp của các phương thức setter được cung cấp bởi giao diện PreparedStatement.. Using prepared statements, we can insert values to advanced datatypes such as BLOB, CLOB, OBJECT easily with the help of the setter methods provided by the PreparedStatement interface.