1

私は PDO を学んでいますが、ステートメントが正しく機能することを確認するのは難しいと感じています。合計に1を追加するだけでデータベースを更新するPHP関数があります。

    function add_rating($place_id,$rating_id) {

    //make $db accessible inside the function
    global $db;

    // query v1
    $sql = "UPDATE places_ratings SET ? +1 WHERE place_id=?";
    $q = $db->prepare($sql);
    $q->execute(array($rating_id,$place_id));   

}

これのバリエーションを試しましたが、どれもうまくいきませんでした。疑問符の使い方が間違っていたかどうかはわかりません。私はこのガイド以前のSOの質問に従っていました。最後に、最初に機能した別の方法を試したので、それを再利用したくなりました。

    function add_rating($place_id,$rating_id) {

    //make $db accessible inside the function
    global $db;

    // query v2
    $query = "UPDATE places_ratings SET $rating_id = ($rating_id +1) WHERE place_id = $place_id";
    $update = $db->query($query);

}

私の質問は次のとおりです。どのステートメントがより優れている/安全ですか? 第二に、疑問符が付いた最初のバージョンで何が間違っているのでしょうか? ありがとう...

4

3 に答える 3

2

プリペアド ステートメントは、単に変数をコピーしてテキストに貼り付けるようなものではありません。プリペアド ステートメントは、クエリ ロジックとクエリが処理するを分離します。それらはそこにあるので、データベースに「あなたはこれを行うことになっている」と伝えることができ、データベースにそれを理解させ、それを行うことになっている値をデータベースに与えることができます。ロジック自体を可変にすることはできません。最初に完了する必要があります。

したがって、値にはプレースホルダーのみを使用できます。クエリを読む必要がありますUPDATE ... SET FIELD = VALUE WHERE FIELD = VALUEFIELDパーツはステートメントに含まれている必要があり、プレースVALUEホルダーを使用できるパーツです。あなたの$rating_id変数は可変フィールド名のようです。まず第一に、それは悪い考えです。可能であれば、フィールド名を変数にしないでください。ただし、必要に応じて、準備済みステートメントのプレースホルダーを使用することはできません。代わりに、次のようにする必要があります。

$rating_id = 'field_name';
$query = "UPDATE places_ratings SET `$rating_id` = `$rating_id` + 1 WHERE `place_id` = ?";
$stmt = $db->prepare($query);
$stmt->execute(array($place_id));

$rating_idが安全で、既知のホワイトリストに登録された値が含まれていることを確認するのはあなた次第です。いかなる方法でも、ユーザーに値を提供させないでください。

于 2012-08-18T07:50:44.577 に答える
2

一般に、最初の例のように準備されたステートメントは、SQL インジェクションの影響を受けないため、より安全です。

?準備されたステートメントでパラメーターを使用してフィールド名を指定できないため、この例は機能しません。SQL がまだ間違っている可能性があるとしても、これは次のように展開されます。

 UPDATE places_ratings SET whatever +1 WHERE place_id=?

これは無効です。

コードで生成され、ユーザー入力から取得されていない場合$rating_idは、両方のアプローチを組み合わせることができます。

于 2012-08-18T07:55:56.773 に答える
1

プリペアド ステートメントとは何かを学んでください。また、悪い慣行や脆弱なコードを助長しないチュートリアルを使用することもできます。

準備済みステートメントはクエリ ロジックとデータを別々に送信するため、正しく作成および使用された準備済みステートメントは、連結されたクエリ文字列よりも常に安全です。

また、PDO を使用している場合は、値を直接メソッドに配列としてbindParam()渡すよりも、メソッドの使用を優先する必要があります。execute()これは、 で値を渡すときに、DB 列が整数を期待していてもexecute()、値が としてバインドされるためです。PDO::PARAM_STR

PSコードでの使用をやめて global ください!!

于 2012-08-18T07:47:54.913 に答える