Транзакция PDO не перехватывает исключения - PullRequest
0 голосов
/ 16 августа 2011

Я пробую транзакции PDO в первый раз. Приведенный ниже код не работает. адрес электронной почты, который мы пытаемся вставить, имеет дубликат, поэтому он должен потерпеть неудачу. Это дает мне ошибку. но первая вставка вставляется в БД, и она не откатывается. Я знаю откат работы, потому что если я переместу PDO :: rollBack в Try {перед фиксацией, он откатится. Я думаю, что проблема в том, что он не перехватывает ошибку, поэтому не вызывает PDO :: rollBack. Есть идеи?

try {
    PDO::beginTransaction();

$sql = "INSERT INTO .`tblUsersIDvsAgencyID` (`id`, `agency_id`) VALUES (NULL, :agencyID)";
$STH = $this->prepare($sql); 
$STH->bindParam(':agencyID', $AgencyUser['agency_id']);
$STH->execute();
$userID = parent::lastInsertId();

$sql = "INSERT INTO `tblUsersEmailAddress` (`id`, `user_id`, `email_address`, `primary`, `created_ts`, `email_verified`) VALUES (NULL ,  :userID ,  :EmailAddress ,  '1', CURRENT_TIMESTAMP ,  '0' )";
$STH = $this->prepare($sql); 
$STH->bindParam(':userID', $userID);
$STH->bindParam(':EmailAddress', $email_address);
$STH->execute();
PDO::commit();
echo 'Data entered successfully<br />';
}
catch(PDOException $e)
{
/*** roll back the transaction if we fail ***/
PDO::rollBack();
echo "failed";
} 

Ответы [ 2 ]

4 голосов
/ 16 августа 2011

PDO::beginTransaction() не является статическим методом. От вашего вопроса, похоже, вы расширяете класс PDO. Я бы не стал этого делать, так как сомневаюсь, что вы добавляете что-то существенное в базовый класс. Вместо этого вы должны установить соединение PDO как свойство класса.

Например

class ParentClass
{
    /**
     * @var PDO
     */
    protected $dbh;

    public function __construct(PDO $dbh)
    {
        $this->dbh = $dbh;

        // Make sure PDO is set to throw exceptions
        $this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }
}

class ChildClass extends ParentClass
{
    public function insertStuff()
    {
        $this->dbh->beginTransaction();
        try {
            // do stuff

            $this->dbh->commit();
        } catch (PDOException $e) {
            $this->dbh->rollBack();
            throw $e;
        }
    }
}
1 голос
/ 16 августа 2011

Я просто начну с цитирования документации:

Осторожно: некоторые типы таблиц MySQL (механизмы хранения) не поддерживают транзакции. При написании кода транзакционной базы данных с использованием типа таблицы, который не поддерживает транзакции, MySQL будет делать вид, что транзакция была успешно инициирована. Кроме того, любые выполненные запросы DDL будут неявно фиксировать все ожидающие транзакции.

Ваша проблема - ожидаемое поведение. Дополнительно:

  1. beginTransaction не является статичным. (Я повторяю заявление Фила о том, что вам не следует расширять PDO).
  2. Вызов $ pdo-> setAttribute (PDO :: ATTR_ERRMODE, PDO :: ERRMODE_EXCEPTION);
  3. Вы никогда не звоните closeCursor в своем заявлении (это часто вызывает проблемы). (Фил указывает, что в этом случае это явно не нужно. Это все же лучшая практика).
  4. Использование bindParam не дает никаких преимуществ для переменной userID, поскольку вы используете ее (локально определенная переменная, которая не используется повторно).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...