2

経験から、そして準備されたステートメントを使用してパラメーターをバインドすることの利点も常に言われてきたため、コードでこれら2つの手法を常に使用してきましたが、これら2つの手法のそれぞれの目的を正確に理解したいと思います。

準備されたステートメントの私の理解から:

$sql = "SELECT * FROM myTable WHERE id = ".$id;
$stmt = $conn->prepare($sql);
$stmt->execute();

前のコードは、私が提案したクエリを使用して、データベースに一種のバッファーを作成する必要があります。私の理解では (そして私は非常に間違っている可能性があります)、前のコードは安全ではありません。文字列は実際の内容に$sql応じて何でもかまいません。$id$id1; DROP TABLE myTable;--

私の理解から、これは私のパラメーターをバインドする場所です。代わりに次のことを行う場合:

$sql = "SELECT * FROM myTable WHERE id = :id";
$stmt = $conn->prepare($sql);
$stmt->bindParam(':id', $id);
$stmt->execute();

データベースは、事前に sql ステートメントのすべての部分を正確に認識している必要があります: SELECTこれらの列:* FROM myTableおよびWHERE id =「ユーザーが入力した変数」、および の場合"a variable that was input by the user" != a variable、クエリは失敗します。

私の理解は正しいと言われた人もいれば、それは間違っていると言われた人もいます。間違っているか、正しいか、または何かが欠けているかどうかを誰かに知らせてもらえますか? すべてのフィードバックは大歓迎です!

4

1 に答える 1

4

最初のケースが安全でないことは正しいです。ただし、変数データを使用している場合、および/または同じクエリを繰り返し実行している場合にのみ、ステートメントの準備が価値があることを理解することが重要です。変数なしで単純なステートメントを実行している場合は、次のように簡単に実行できます。

$sql = "SELECT * from myTable WHERE this_column IS NOT NULL";
$result = $conn->query($sql);

そしてPDOStatement、 を使用するときと同じように、操作するオブジェクトになりますPDO::exec()

2 番目のケースについても、おおむね正しいです。何が起こっているのかというと、データベースに渡される変数はエスケープされ、引用符で囲まれます (への 3 番目の引数で特に指定しない限りPDOStatement::bindParam()、ほとんどの場合問題ない文字列として送信されます)。送信されます。データベースに ID として存在しない有効な数値を渡した場合とまったく同じように動作します。もちろん、正しく準備されたステートメントを使用しても脆弱なエッジ ケースがいくつかあります。

また、生活を楽にするために、次のような準備済みステートメントを使用して、暗黙的なバインドを行うことができます。

$sql = "SELECT * FROM myTable WHERE id = :id";
$stmt = $conn->prepare($sql);
$stmt->execute([":id"=>$id]);

または、名前のないパラメーターを使用して、次のようにします。

$sql = "SELECT * FROM myTable WHERE id = ?";
$stmt = $conn->prepare($sql);
$stmt->execute([$id]);

当然のことながら、これのほとんどは、私が答えを入力している間にコメントで説明されました!

于 2016-05-09T20:04:39.413 に答える