Моя цель – одновременно использовать транзакцию и подготовленный отчет, чтобы обеспечить как целостность данных, так и предотвращение 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; }
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; } }
Просто вызовите «выполнить» после вызова «beginTransaction».
То, что вы называете «подготовкой», не имеет большого значения.
Вот полный пример:
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) Основываясь на ответе на ваш комментарий выше, я думаю, что вы можете ввести в заблуждение «выполнить» и «начать tran / commit». Посмотрите мою ссылку.
3) Вам даже нужна сделка? Вы просто делаете два «выбора».
4) Наконец, почему бы не сделать одно «соединение» (или объединение, если оно совместимо) вместо двух «выбрать»?
Вы имели в виду это?
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=?