PHP PDO 没有活动事务
PHP PDO There is no active transaction
我尝试 运行 使用 PDO class 进行查询并收到此错误消息:"There is no active transaction"
尝试提交时。
这是我的代码:
public function runExQuery($sql) {
$preparedQuery = $this->connect()->prepare($sql);
$this->connect()->beginTransaction();
$preparedQuery->execute();
$this->connect()->commit();
}
private function connect() {
return new PDO('mysql:host=' . $this->host . ';dbname=' . $this->database . '', $this->username, $this->password);
}
这个错误的原因是什么?我探索了此类问题的先前帖子,但没有找到任何解决方案。
您的 ::connect()
方法在您每次调用时都会创建一个新的 PDO。
由于事务在连接之外无法存活,因此重新连接会将其清除。
要更正此问题,请将 PDO 对象存储为 class 属性:
class MyPdoClass
{
private $pdo;
// ...
public function connect()
{
if ($this->pdo instanceof PDO) {
return;
}
$this->pdo = new PDO(// ....
}
调用connect后引用:
//...
public function runExQuery($query)
{
$this->connect();
$this->pdo->prepare($query);
// ...
}
您每次调用 $this->connect()
时都会创建一个新的 PDO 对象,因此如果您有:
$stmt1 = $this->connect()->prepare(" ... ");
$stmt2 = $this->connect()->prepare(" ... ");
$stmt1
和 $stmt2
实际上是完全不同的 PDO 对象,因此如果您使用一个对象启动事务,它将不适用于另一个对象。相反,您应该保存一个 PDO 对象并引用它,而不是每次都创建一个新对象。
大多数时候,我发现将其传递给 class 的构造函数更容易,但是如果您想进行最少的编辑,您可以这样做:
class YourClass {
private $dbh;
private function connect() {
if (!isset($this->dbh)) {
$this->dbh = new PDO('mysql:host=' . $this->host . ';dbname=' . $this->database, $this->username, $this->password);
}
return $this->dbh;
}
}
但是您可能希望将名称 connect()
更改为更合乎逻辑的名称,例如 getDbh()
.
如果您想将它放在对象的构造函数中,您可以这样做:
class YourClass {
private $dbh;
public function __construct(PDO $dbh) {
$this->dbh = $dbh;
}
}
$dbh = new PDO('mysql:host=' . $host . ';dbname=' . $database, $username, $password);
$yourclass = new YourClass($dbh);
然后在任何其他 class 方法中,您只需引用 $this->dbh
。以您的代码为例:
public function runExQuery($sql) {
$preparedQuery = $this->dbh->prepare($sql);
$this->dbh->beginTransaction();
$preparedQuery->execute();
$this->dbh->commit();
}
就个人而言,这就是我的做法。
我尝试 运行 使用 PDO class 进行查询并收到此错误消息:"There is no active transaction"
尝试提交时。
这是我的代码:
public function runExQuery($sql) {
$preparedQuery = $this->connect()->prepare($sql);
$this->connect()->beginTransaction();
$preparedQuery->execute();
$this->connect()->commit();
}
private function connect() {
return new PDO('mysql:host=' . $this->host . ';dbname=' . $this->database . '', $this->username, $this->password);
}
这个错误的原因是什么?我探索了此类问题的先前帖子,但没有找到任何解决方案。
您的 ::connect()
方法在您每次调用时都会创建一个新的 PDO。
由于事务在连接之外无法存活,因此重新连接会将其清除。
要更正此问题,请将 PDO 对象存储为 class 属性:
class MyPdoClass
{
private $pdo;
// ...
public function connect()
{
if ($this->pdo instanceof PDO) {
return;
}
$this->pdo = new PDO(// ....
}
调用connect后引用:
//...
public function runExQuery($query)
{
$this->connect();
$this->pdo->prepare($query);
// ...
}
您每次调用 $this->connect()
时都会创建一个新的 PDO 对象,因此如果您有:
$stmt1 = $this->connect()->prepare(" ... ");
$stmt2 = $this->connect()->prepare(" ... ");
$stmt1
和 $stmt2
实际上是完全不同的 PDO 对象,因此如果您使用一个对象启动事务,它将不适用于另一个对象。相反,您应该保存一个 PDO 对象并引用它,而不是每次都创建一个新对象。
大多数时候,我发现将其传递给 class 的构造函数更容易,但是如果您想进行最少的编辑,您可以这样做:
class YourClass {
private $dbh;
private function connect() {
if (!isset($this->dbh)) {
$this->dbh = new PDO('mysql:host=' . $this->host . ';dbname=' . $this->database, $this->username, $this->password);
}
return $this->dbh;
}
}
但是您可能希望将名称 connect()
更改为更合乎逻辑的名称,例如 getDbh()
.
如果您想将它放在对象的构造函数中,您可以这样做:
class YourClass {
private $dbh;
public function __construct(PDO $dbh) {
$this->dbh = $dbh;
}
}
$dbh = new PDO('mysql:host=' . $host . ';dbname=' . $database, $username, $password);
$yourclass = new YourClass($dbh);
然后在任何其他 class 方法中,您只需引用 $this->dbh
。以您的代码为例:
public function runExQuery($sql) {
$preparedQuery = $this->dbh->prepare($sql);
$this->dbh->beginTransaction();
$preparedQuery->execute();
$this->dbh->commit();
}
就个人而言,这就是我的做法。