TECH I.S.

PHP MySQLプリペアド ステートメント


準備済みステートメントは、SQLインジェクションに対して非常に役立ちます。


プリペアド ステートメントとバインドされたパラメーター

準備済みステートメントは、同じ(または類似した)SQLステートメントを効率よく繰り返し実行するために使用される機能です。

プリペアド ステートメントは、基本的に次のように機能します。

  1. 準備: SQLステートメントテンプレートが作成され、データベースに送信されます。特定の値は未指定のままで、パラメーターと呼ばれます (「?」のラベルが付いています)。例: INSERT INTO MyGuests VALUES(?, ?, ?)
  2. データベースは、SQLステートメントテンプレートに対してクエリの解析、コンパイル、および最適化を実行し、結果を実行せずに格納します。
  3. 実行: 後で、アプリケーションが値をパラメーターにバインドし、データベースがステートメントを実行します。アプリケーションは、異なる値を使用してステートメントを何度でも実行できます。

SQLステートメントを直接実行する場合と比較して、準備済みステートメントには次の3つの主な利点があります。

  • 準備されたステートメントは、クエリの準備が1回だけ行われるため、解析時間を短縮します(ただし、ステートメントは複数回実行されます)。
  • バインドされたパラメーターは、クエリ全体ではなくパラメーターのみを毎回送信する必要があるため、サーバーへの帯域幅を最小限に抑えます
  • 後で別のプロトコルを使用して送信されるパラメーター値を正しくエスケープする必要がないため、準備済みステートメントはSQLインジェクションに対して非常に役立ちます。元のステートメント テンプレートが外部入力から派生していない場合、SQLインジェクションは発生しません。

MySQLiのプリペアドステートメント

次の例では、MySQLiで準備済みステートメントとバインドされたパラメーターを使用しています。

例 (プリペアドステートメントを使用するMySQLi)

<?php $servername = "localhost"; $username = "username"; $password = "password"; $dbname = "myDB"; // Create connection $conn = new mysqli($servername, $username, $password, $dbname); // Check connection if ($conn->connect_error) {   die("Connection failed: " . $conn->connect_error); } // prepare and bind $stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)"); $stmt->bind_param("sss", $firstname, $lastname, $email); // set parameters and execute $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 "New records created successfully"; $stmt->close(); $conn->close(); ?>

上記の例から説明するコード行は次のとおりです。:

"INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)"

SQLでは、整数、文字列、double、またはblob値を置換する場所に疑問符(?)を挿入します。

次に、bind_param()関数を見てください。

$stmt->bind_param("sss", $firstname, $lastname, $email);

この関数は、パラメーターをSQLクエリにバインドし、パラメーターが何であるかをデータベースに伝えます。 「sss」引数には、パラメーターのデータのタイプがリストされます。s文字は、パラメーターが文字列であることをmysqlに伝えます。

引数は、次の4つのタイプのいずれかです。

  • i - integer
  • d - double
  • s - string
  • b - BLOB

パラメータごとにこれらのいずれかが必要です。

期待するデータのタイプをmysqlに伝えることで、SQLインジェクションのリスクを最小限に抑えます。


注:外部ソース(ユーザー入力など)からデータを挿入する場合は、データをサニタイズして検証することが非常に重要です。





PDOのプリペアド ステートメント

次の例では、PDOでプリペアドステートメントとバインドされたパラメーターを使用しています。

例 (プリペアドステートメントを含むPDO)

<?php $servername = "localhost"; $username = "username"; $password = "password"; $dbname = "myDBPDO"; try {   $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);   // prepare sql and bind parameters   $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);   // insert a row   $firstname = "John";   $lastname = "Doe";   $email = "john@example.com";   $stmt->execute();   // insert another row   $firstname = "Mary";   $lastname = "Moe";   $email = "mary@example.com";   $stmt->execute();   // insert another row   $firstname = "Julie";   $lastname = "Dooley";   $email = "julie@example.com";   $stmt->execute();   echo "New records created successfully"; } catch(PDOException $e) {   echo "Error: " . $e->getMessage(); } $conn = null; ?>



プログラミング学習を加速させる

プログラミングをプロの講師に教えてもらいませんか。

テックアイエスのプログラミングスクールは初心者も大歓迎です。年齢制限もありません。転職・副業に強く、挫折させない手厚いサポートで稼ぐ力を身につけましょう!

スクールの詳細