1

我尝试使用 PDO 类运行查询并收到此错误消息:"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);
    }

这个错误的原因是什么?我探索了此类问题的先前帖子,但没有找到任何解决方案。

4

2 回答 2

3

您的::connect()方法是在每次调用它时创建一个新的 PDO。

由于事务在连接之外无法生存,因此重新连接会将其清除。

要更正此问题,请将 PDO 对象存储为类属性:

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);
        // ... 
    }
于 2015-06-01T21:28:58.870 回答
2

每次调用时都会创建一个新的 PDO 对象$this->connect(),因此如果您有:

$stmt1 = $this->connect()->prepare(" ... ");
$stmt2 = $this->connect()->prepare(" ... ");

$stmt1并且$stmt2实际上将是完全不同的 PDO 对象,因此如果您使用一个对象启动事务,它将不适用于另一个对象。相反,您应该保存一个 PDO 对象并引用它,而不是每次都创建一个新对象。

大多数时候,我发现将它传递给类的构造函数更容易,但是如果你想做最少的编辑,你可以这样做:

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);

然后在任何其他类方法中,您只需引用$this->dbh. 以您的代码为例:

public function runExQuery($sql) {
    $preparedQuery = $this->dbh->prepare($sql);
    $this->dbh->beginTransaction();
    $preparedQuery->execute();
    $this->dbh->commit();
}

就个人而言,这是我会做的方式。

于 2015-06-01T21:29:51.807 回答