Как я могу использовать подготовленные операторы в сочетании с транзакциями с PHP?

Моя цель - использовать транзакцию и подготовленный оператор одновременно для достижения как целостности данных, так и предотвращения внедрения 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));

Как я могу этого достичь?

Edit

Я получаю эту ошибку:

PHP Parse error: syntax error, unexpected 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; 
    }
 DCoder17 мая 2012 г., 22:00
Ты можешь переформулировать вопрос?
 alexx018617 мая 2012 г., 22:07
Нет, потому что я не знаю, что делать сcommit() а такжеexecute() потому что они должны делать примерно то же самое
 paulsm417 мая 2012 г., 22:19
Нет, "совершить" и "выполнить" Не "делай примерно то же самое";)
 Andrew Willis17 мая 2012 г., 22:30
в конце вы не видите закрывающую скобку в операторе WHILE
 alexx018617 мая 2012 г., 22:21
Я ожидал этого ответа, я просил об этом .. :) Что делает commit? Я думал, что он отправил / выполнил все запросы в целом

Ответы на вопрос(3)

Решение Вопроса
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; 
    }
}
 DCoder17 мая 2012 г., 22:10
1) если сгенерирует конструктор PDO, блок catch вызовет уведомление о неопределенной переменной. 2) полное проглатывание сообщения об ошибке не очень хорошая идея. В реальном мире фактическое сообщение и трассировка стека должны быть зарегистрированы.
 Andrew Willis17 мая 2012 г., 22:11
да, но заданный вопрос не касался обработки ошибок, поэтому ваш ответ приемлем
 Andrew Willis17 мая 2012 г., 22:09
Это немного не хватает
 Jeroen17 мая 2012 г., 22:10
Я даже не смотрел на обработку исключений, но DCoder абсолютно прав, это тоже должно быть улучшено
 PeeHaa17 мая 2012 г., 22:14
$cxn ->$cnx?

Ты имел в виду это?

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";
}

Предполагается, что данные двух таблиц не имеют повторяющихся имен полей, в противном случае вам придется использовать:

SELECT users.field1 as u_field1, othertable.field1 as o_field1 FROM users, othertable 
WHERE users.username=? 
AND othertable.some_column=?
 alexx018617 мая 2012 г., 22:48
Привет, спасибо за ваш ответ. На самом деле я использовал два запроса SELECT в качестве примера, но я также хочу использовать запросы UPDATE. С уважение
 Andrew Willis18 мая 2012 г., 18:10
Dev.mysql.com / DOC / RefMan / 5.0 / ен / join.html имеет примеры использования объединений для запросов UPDATE / DELETE / SELECT

Где бы вы ни назвали «готовиться», это не имеет значения.

Вот полный пример:

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

ПРИМЕР

 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) Исходя из вашего комментария, приведенного выше, я думаю, что вы можете запутать слова "execute" и "begin tran / commit". Пожалуйста, посмотрите на мою ссылку.

3) Ты хотьнужн сделка? Вы просто делаете два "выбора".

4) И наконец, почему бы не сделать одно «соединение» (или объединение, если оно совместимо) вместо двух «выбора»?

 Andrew Willis17 мая 2012 г., 22:26
Я предложил объединить в своем ответе, думаю, именно это он имел в виду под "Incorporate as one"

Ваш ответ на вопрос