MySQLステートメント内にPHP変数を追加するルールは、単純明快です。
- SQLデータリテラルを表す変数 、(または、簡単に言うと、SQL文字列または数値)は、プリペアドステートメントを介して追加する必要があります。例外はありません。
- SQLキーワード、テーブル名、フィールド名、演算子など、その他のクエリ部分は、ホワイトリストでフィルタリングする必要があります。 。
したがって、この例にはデータリテラルのみが含まれているため、すべての変数はプレースホルダー(パラメーターとも呼ばれます)を介して追加する必要があります。そのためには:
- SQLステートメントで、すべての変数をプレースホルダーに置き換えます。
- 準備 結果のクエリ
- バインド プレースホルダーへの変数
- 実行 クエリ
そして、これがすべての人気のあるPHPデータベースドライバーでそれを行う方法です:
mysqlextを使用したデータリテラルの追加
そのようなドライバーは
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();
コードは少し複雑ですが、これらすべての演算子の詳細な説明は、私の記事実行方法にあります。 Mysqliを使用したINSERTクエリ 、およびプロセスを劇的に容易にするソリューション。
SELECTクエリの場合、get_result()
への呼び出しを追加するだけで済みます。 おなじみのmysqli_result
を取得するメソッド 通常の方法でデータを取得できます:
$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 (...)
PDOを使用したデータリテラルの追加
$type = 'testing';
$reporter = "John O'Hara";
$query = "INSERT INTO contents (type, reporter, description)
VALUES(?, ?, 'whatever')";
$stmt = $pdo->prepare($query);
$stmt->execute([$type, $reporter]);
PDOでは、バインド部分と実行部分を組み合わせることができるので、とても便利です。 PDOは、非常に便利な名前付きプレースホルダーもサポートしています。
キーワードまたは識別子の追加
キーワードや識別子(データベース、テーブル、フィールド名)など、クエリの別の部分を表す変数を追加する必要がある場合があります。まれなケースですが、準備しておくことをお勧めします。
この場合、変数は値のリストに対して明示的にチェックする必要があります スクリプトに記述されています。これについては、他の記事ユーザーの選択に基づいてORDERBY句にフィールド名を追加する> :
残念ながら、PDOには識別子(テーブル名とフィールド名)のプレースホルダーがないため、開発者はそれらを手動で除外する必要があります。このようなフィルターは、許可されていない値をリストする「ブラックリスト」とは対照的に、「ホワイトリスト」(許可された値のみをリストする)と呼ばれることがよくあります。
そのため、PHPコードで考えられるすべてのバリアントを明示的にリストし、それらから選択する必要があります。
次に例を示します:
$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");
}
方向性については、まったく同じアプローチを使用する必要があります。
$direction = $_GET['direction'] ?: "ASC";
$allowed = ["ASC","DESC"];
$key = array_search($direction, $allowed, true);
if ($key === false) {
throw new InvalidArgumentException("Invalid ORDER BY direction");
}
そのようなコードの後、両方の$direction
および$orderby
変数は、許可されているバリアントの1つと等しいか、エラーがスローされるため、SQLクエリに安全に配置できます。
識別子について最後に言及することは、特定のデータベース構文に従ってフォーマットする必要があることです。 MySQLの場合は、backtick
である必要があります 識別子の周りの文字。したがって、例による注文の最終的なクエリ文字列は次のようになります
$query = "SELECT * FROM `table` ORDER BY `$orderby` $direction";