8

私の目標は、トランザクションとプリペアドステートメントを同時に使用して、データの整合性とSQLインジェクションの防止の両方を実現することです。

私はこれを持っています:

   try {
        $cnx = new PDO($dsn,$dbuser,$dbpass);   
        $cnx->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

        $cnx->beginTransaction();
        $cnx->query("SELECT * FROM users WHERE username=$escaped_input");
        $cnx->query("SELECT * FROM othertable WHERE some_column=$escaped_input_2");

        $cnx->commit();
    }

    catch (Exception $e){
           $cxn->rollback();
           echo "an error has occured";

    }

プリペアドステートメントの場合と同じように、クエリを組み込みたいと思います。

$stmt=$cxn->prepare("SELECT * FROM users WHERE username=?");
$stmt->execute(array($user_input));

$stmt_2=$cxn->prepare("SELECT * FROM othertable WHERE some_column=?");
$stmt_2->execute(array($user_input_2));

どうすればそれを達成できますか?

編集

このエラーが発生します:

PHP解析エラー:構文エラー、予期しないT_CATCH

これが私の更新されたコードです:

try 
{
    $cnx = new PDO($dsn,$dbuser,$dbpass);   
    $cnx->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $cnx->beginTransaction();
    $stmt=$cnx->prepare("SELECT * FROM users WHERE username=?");
    $stmt->execute(array($username));

    $cnx->commit();

    while ($row=$stmt->fetch(PDO::FETCH_OBJ)){
    echo $stmt->userid;

}

catch(Exception $e) { 
    if (isset($cnx)) 
        $cnx->rollback();
       echo "Error:  " . $e; 
    }
4

3 に答える 3

12

「beginTransaction」を呼び出した後、「execute」を呼び出すだけです。

「準備」と呼ぶ場所は実際には重要ではありません。

完全な例を次に示します。

http://php.net/manual/en/pdo.begintransaction.php

例:

 try {
    $cnx = new PDO($dsn,$dbuser,$dbpass);   
    $cnx->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $cnx->beginTransaction();

    $stmt=$cxn->prepare("SELECT * FROM users WHERE username=?");
    $stmt->execute(array($user_input));

    $stmt_2=$cxn->prepare("SELECT * FROM othertable WHERE some_column=?");
    $stmt_2->execute(array($user_input_2));

    $cnx->commit();
  }
  catch (Exception $e){
    $cxn->rollback();
    echo "an error has occurred";
  }

PS:1)もちろん、$user_inputと$user_input_2はすぐに利用できると思います。トランザクションが不必要に長く開いたままになるのは望ましくありません;)

2)上記のコメントの返信から、「実行」と「トラン/コミットの開始」を混同しているのではないかと思います。私のリンクを見てください。

3)取引も必要ですか?あなたはただ2つの「選択」をしているだけです。

4)最後に、2つの「選択」の代わりに1つの「結合」(または互換性がある場合は結合)を実行してみませんか?

于 2012-05-17T20:07:09.500 に答える
11
try 
{
    $cnx = new PDO ($dsn,$dbuser,$dbpass);   
    $cnx->setAttribute (PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $cnx->beginTransaction ();

    $stmt = $cnx->prepare ("SELECT * FROM users WHERE username=?");
    $stmt->execute(array($username));

    $cnx->commit();

    while ($row = $stmt->fetch (PDO::FETCH_OBJ)){
        echo $row->userid;
    }
}

catch (Exception $e) { 
    if (isset ($cnx)) 
        $cnx->rollback ();
       echo "Error:  " . $e; 
    }
}
于 2012-05-17T20:06:42.627 に答える
1

これですか?

try {
    $cnx = new PDO($dsn,$dbuser,$dbpass);   
    $cnx->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $cnx->beginTransaction();
    $stmt=$cnx->prepare("
        SELECT * FROM users, othertable 
        WHERE users.username=? 
        AND othertable.some_column=?");

    $stmt->execute(array($user_input,$user_input_2));

    $cnx->commit();
}
catch (Exception $e){
       $cnx->rollback();
       echo "an error has occured";
}

これは、2つのテーブルデータに重複するフィールド名がないことを前提としています。そうでない場合は、次を使用する必要があります。

SELECT users.field1 as u_field1, othertable.field1 as o_field1 FROM users, othertable 
WHERE users.username=? 
AND othertable.some_column=?
于 2012-05-17T20:19:23.137 に答える