【问题标题】:Why does my PHP transaction not work?为什么我的 PHP 事务不起作用?
【发布时间】:2017-06-22 20:14:17
【问题描述】:

我正在为我的作品集网站创建一个 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!";
    }
}

【问题讨论】:

  • 错误报告?查询错误会触发任何类型的警告/通知吗?
  • 啊.. 我有ini_set("display_errors", true); 但没有error_reporting(E_ALL); 这应该可以帮助我解决这个问题。

标签: php mysql pdo


【解决方案1】:

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

【讨论】:

  • 我正在使用 MySQL Workbench。但我确实知道这些表是 MyISAM。虽然我确实有一个与此类似的 Insert 函数,它可以同时插入到项目表和 content_category 表中,并且工作正常。
  • 不看代码就不确定。阅读文档后,如果您正在运行 MyISAM 表,它应该会抛出错误并且不执行任何操作。 us3.php.net/manual/en/pdo.transactions.php
【解决方案2】:

为了确保您没有遇到 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 documentation,如果您的数据库不支持事务,您会遇到异常...

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

【讨论】:

  • 我终于能够让它工作......问题不在于交易(尽管我确实意识到拥有 beginTranaction 行并没有真正做任何事情......我删除了)...... . 我的 $projectID 变量没有设置,所以它不知道要更新哪个项目。感谢大家的提示。祝您编码愉快!
【解决方案3】:

Commit 成功时返回 TRUE,失败时返回 FALSE。你可以检查一下。还要检查errorCode

【讨论】:

    猜你喜欢
    • 2021-07-06
    • 2017-02-26
    • 2023-04-04
    • 2018-05-14
    • 2012-10-07
    • 1970-01-01
    • 1970-01-01
    • 2016-11-08
    • 1970-01-01
    相关资源
    最近更新 更多