为什么我的PHP事务不起作用


Why does my PHP transaction not work?

我正在做一个学校项目,为我的投资组合网站创建CMS。我的更新功能无法正常工作。我有一种感觉,这与我构建PDO事务的方式有关。在我的数据库中,我有一个项目表、类别表和关联的content_category表。我可以很好地将我的项目插入到这些表中。我想做的是插入到我的项目表中,然后从content_category表中删除所有记录,最后将当前类别记录插入到该关联表中以完成事务。我确实收到了我的退货声明"项目更新"。但这些表格并没有更新。有什么想法吗?

这是代码:

这是我的Project类中的一个函数。

public function update(){
    try {
        $conn = getConnection();
        $conn->beginTransaction();
        $sql = "UPDATE project 
                SET project_title = :title, 
                    project_description = :desc, 
                    project_isFeatured = :feat, 
                    project_mainImage = :image
                WHERE project_id = :id";
        $st = $conn->prepare($sql);
        $st->bindValue(":id", $this->id, PDO::PARAM_INT);
        $st->bindValue(":title", $this->title, PDO::PARAM_STR);
        $st->bindValue(":desc", $this->description, PDO::PARAM_STR);
        $st->bindValue(":feat", $this->isFeatured, PDO::PARAM_BOOL);            
        $st->bindValue(":image", $this->mainImage, PDO::PARAM_INT);
        $st->execute(); 
        $sql = "DELETE from content_category
                WHERE content_id = :id";
        $st = $conn->prepare($sql);
        $st->bindValue("id", $this->id, PDO::PARAM_INT);
        $st->execute();
        $sql = "INSERT into content_category (content_id, cat_id)
                VALUES (?,?)";
        $st = $conn->prepare($sql);
        foreach($this->categories as $key=>$value){
            $st->execute(array(intval($projectID), intval($value)));                                        
        }
        $conn->commit();
        $conn = null;
        return "Project updated";                   
    }
    catch(Exception $e) {
        echo $e->getMessage();
        $conn->rollBack();
        return "Error... Unable to update!";
    }
}

表的数据库引擎需要是INNODB。如果您使用的是phpMyAdmin,则默认为MyISAM。(我不知道这是否会导致更新无法通过,或者只是事务行被忽略。编辑:很确定文档中说,如果你在myISAM上启动transaction,它会抛出一个错误,并且不会做任何事情)

为了确保您没有遇到PDO错误,您应该这样设置PDO错误报告:

$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

PDO中有一些函数,如prepare(),根据设置的错误模式,它们要么返回false,要么抛出PDOException。这样,它会抛出一个异常,你肯定会知道自己是否有问题!

此外,如果数据库不支持事务(如MyISAM),beginTransaction()函数将返回false。所以,也许可以在那里添加一个支票,比如:

if($conn->beginTransaction()) {
   // Do transaction here
} else {
   echo("Unable to use transactions with this database.");
}

奇怪的是,根据PHP文档,如果你的数据库不支持事务,你会得到一个异常。。。

不幸的是,并不是每个数据库都支持事务,所以当您第一次打开连接时,PDO需要以所谓的"自动提交"模式运行。自动提交模式意味着,如果数据库支持,运行的每个查询都有自己的隐式事务;如果数据库不支持事务,则没有事务。如果您需要一个事务,则必须使用PDO::beginTransaction()方法来启动一个事务如果底层驱动程序不支持事务,则会引发PDOException(无论您的错误处理设置如何:这始终是严重的错误情况)

Commit在成功时返回TRUE,在失败时返回FALSE。你可以检查它。也可以检查errorCode。