PHP MySQL 準備済みステートメント
PHP MySQL プリペアド ステートメント
プリペアド ステートメントは、MySQL インジェクションを防ぐのに非常に役立ちます。
プリペアドステートメントとバインドパラメータ
プリペアドステートメントは、複數(shù)の同一の SQL ステートメントをより高い実行効率で実行するために使用されます。
準備されたステートメントの動作原理は次のとおりです:
1. 前処理: SQL ステートメントのテンプレートを作成し、データベースに送信します。予約された値にはパラメータ「?」が付けられます。例:
2. INSERT
INTO MyGuests (firstname, lastname, email) VALUES(?, ?, ?)
3. SQL ステートメント テンプレートのデータベース解析、コンパイル、クエリの最適化、および出力なしの結(jié)果の保存。
4. 実行: 最後に、アプリケーションにバインドされた値をパラメーター (「?」マーク) に渡すと、データベースがステートメントを?qū)g行します。パラメータ値が異なる場合、アプリケーションはステートメントを複數(shù)回実行できます。
SQL ステートメントを直接実行する場合と比較して、プリペアド ステートメントには 2 つの主な利點があります:
· 前処理されたステートメントは分析時間を大幅に短縮し、クエリを 1 つだけ作成します (ステートメントは複數(shù)回実行されますが)。
· パラメーターをバインドするとサーバーの帯域幅が削減され、ステートメント全體ではなくクエリのパラメーターのみを送信する必要があります。
· プリペアド ステートメントは、パラメーター値が送信された後にさまざまなプロトコルが使用され、データの合法性が保証されるため、SQL インジェクションに非常に役立ちます。
MySQLi プリペアドステートメント
次の例では、MySQLi でプリペアドステートメントを使用し、対応するパラメータをバインドします:
例 (MySQLi はプリペアドステートメントを使用します)
<?php $servername = "localhost"; $username = "username"; $password = "password"; $dbname = "myDB"; // 創(chuàng)建連接 $conn = new mysqli($servername, $username, $password, $dbname); // 檢測連接 if ($conn->connect_error) { die("連接失敗: " . $conn->connect_error); } // 預處理及綁定 $stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email) VALUES(?, ?, ?)"); $stmt->bind_param("sss", $firstname, $lastname, $email); // 設置參數(shù)并執(zhí)行 $firstname = "John"; $lastname = "Doe"; $email = "john@example.com"; $stmt->execute(); $firstname = "Mary"; $lastname = "Moe"; $email = "mary@example.com"; $stmt->execute(); $firstname = "Julie"; $lastname = "Dooley"; $email = "julie@example.com"; $stmt->execute(); echo "新記錄插入成功"; $stmt->close(); $conn->close(); ?>
次の例のコードの各行を解析します:
"INSERT INTO MyGuests (firstname, lastname, email) VALUES(?, ?, ?)"
SQL ステートメントでは疑問符 (?) を使用します。ここで、疑問符を整數(shù)、文字列、倍精度浮動小數(shù)點、および倍精度浮動小數(shù)點數(shù)に置き換えることができます。ブール値。
次に、bind_param() 関數(shù)を見てみましょう:
$stmt->bind_param("sss", $firstname, $lastname, $email);
この関數(shù)は SQL パラメーターをバインドし、データベースに通知します。パラメータの値。 「sss」パラメータ列は、殘りのパラメータのデータ型を処理します。 s 文字は、パラメータが文字列であることをデータベースに伝えます。
パラメータには次の 4 種類があります:
?i - integer (整數(shù))
?d - double (倍精度浮動小數(shù)點型)
?s - string (文字列)
?b - BLOB (バイナリ?ラージ)オブジェクト: バイナリ ラージ オブジェクト)
各パラメータには型を指定する必要があります。
データベースにパラメータのデータ型を伝えることで、SQL インジェクションのリスクを軽減できます。
注: 他のデータ (ユーザー入力) を挿入する場合は、データの検証が非常に重要です。
PDO のプリペアドステートメント
次の例では、PDO で準備されたステートメントを使用し、パラメーターをバインドします:
例 (PDO は準備されたステートメントを使用します)
<?php $servername = "localhost"; $username = "username"; $password = "password"; $dbname = "myDBPDO"; try { $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password); // 設置 PDO 錯誤模式為異常 $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // 預處理 SQL 并綁定參數(shù) $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); // 插入行 $firstname = "John"; $lastname = "Doe"; $email = "john@example.com"; $stmt->execute(); // 插入其他行 $firstname = "Mary"; $lastname = "Moe"; $email = "mary@example.com"; $stmt->execute(); // 插入其他行 $firstname = "Julie"; $lastname = "Dooley"; $email = "julie@example.com"; $stmt->execute(); echo "新記錄插入成功"; } catch(PDOException $e) { echo $sql . "<br>" . $e->getMessage(); } $conn = null; ?>