我是第一次尝试PDO交易。以下代码不起作用。我们尝试插入的电子邮件地址有重复,因此它应该失败。它确实给了我一个错误。但是第一个插入插入到DB中并且它不会回滚。我知道回滚工作如果我将PDO :: rollBack移动到Try {before commit之前,它会回滚。我认为问题是它没有捕获错误,因此没有调用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";
}
答案 0 :(得分:4)
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 :(得分:1)
我将首先引用文档:
注意:某些MySQL表类型(存储引擎)不支持事务。使用不支持事务的表类型编写事务数据库代码时,MySQL将假装成功启动了事务。此外,发出的任何DDL查询都将隐式提交任何挂起的事务。
您的问题可能是预期的行为。此外:
beginTransaction
不是静态的。 (我重复菲尔的声明,你不应该扩展PDO)。closeCursor
(这通常会导致问题)。 (菲尔指出在这种情况下没有明确的必要。尽管如此,这仍然是最好的做法。)bindParam
并不会因为使用它而对userID变量产生任何好处(本地定义的变量不会被重复使用)。