PHP PDO事务?

PHP PDO事务?,php,transactions,pdo,mysqli,multi-query,Php,Transactions,Pdo,Mysqli,Multi Query,我有一个注册页面,基本上我需要在4个表中插入数据。我是PDO的新手,对一些事情感到困惑 基本上,如果任何插入失败,我不希望向数据库中添加任何内容,这似乎足够简单 我的困惑是,我需要首先在我的users表中插入用户用户名、电子邮件、密码等,这样我就可以使用uid MySQL提供给我的用户的PDO(不确定如何获得)(由MySQL自动递增)。我需要MySQL为我的用户提供的其他表的用户uid,因为其他表需要uid,所以所有内容都正确链接在一起。我的表是InnoDB,外键从users\u profile

我有一个注册页面,基本上我需要在4个表中插入数据。我是PDO的新手,对一些事情感到困惑

基本上,如果任何插入失败,我不希望向数据库中添加任何内容,这似乎足够简单

我的困惑是,我需要首先在我的
users
表中插入用户用户名、电子邮件、密码等,这样我就可以使用uid MySQL提供给我的用户的PDO(不确定如何获得)(由MySQL自动递增)。我需要MySQL为我的用户提供的其他表的用户uid,因为其他表需要uid,所以所有内容都正确链接在一起。我的表是InnoDB,外键从users\u profiles(user\u uid)、users\u status(user\u uid)、users\u roles(user\u uid)到users.user\u uid,因此它们都链接在一起

但同时我想确保,例如,如果在
users
表中插入数据之后(这样我就可以得到MySQL提供给用户的uid),如果任何其他插入失败,它将删除插入
users
表中的数据

我认为我最好展示我的代码;我已经注释掉了代码,并在代码中进行了解释,这可能会使代码更容易理解

// Begin our transaction, we need to insert data into 4 tables:
// users, users_status, users_roles, users_profiles
// connect to database
$dbh = sql_con();

// begin transaction
$dbh->beginTransaction();

try {

    // this query inserts data into the `users` table
    $stmt = $dbh->prepare('
                        INSERT INTO `users`
                        (users_status, user_login, user_pass, user_email, user_registered)
                        VALUES
                        (?, ?, ?, ?, NOW())');

    $stmt->bindParam(1, $userstatus,     PDO::PARAM_STR);
    $stmt->bindParam(2, $username,       PDO::PARAM_STR);
    $stmt->bindParam(3, $HashedPassword, PDO::PARAM_STR);
    $stmt->bindParam(4, $email,          PDO::PARAM_STR);
    $stmt->execute();

    // get user_uid from insert for use in other tables below
    $lastInsertID = $dbh->lastInsertId();

    // this query inserts data into the `users_status` table
    $stmt = $dbh->prepare('
                        INSERT INTO `users_status`
                        (user_uid, user_activation_key)
                        VALUES
                        (?, ?)');

    $stmt->bindParam(1, $lastInsertID,     PDO::PARAM_STR);
    $stmt->bindParam(2, $activationkey,    PDO::PARAM_STR);
    $stmt->execute();

    // this query inserts data into the `users_roles` table
    $stmt = $dbh->prepare('
                        INSERT INTO `users_roles`
                        (user_uid, user_role)
                        VALUES
                        (?, ?)');

    $stmt->bindParam(1, $lastInsertID,      PDO::PARAM_STR);
    $stmt->bindParam(2, SUBSCRIBER_ROLE,    PDO::PARAM_STR);
    $stmt->execute();

    // this query inserts data into the `users_profiles` table
    $stmt = $dbh->prepare('
                        INSERT INTO `users_profiles`
                        (user_uid)
                        VALUES
                        (?)');

    $stmt->bindParam(1, $lastInsertID,      PDO::PARAM_STR);
    $stmt->execute();

    // commit transaction
    $dbh->commit();

} // any errors from the above database queries will be catched
catch (PDOException $e) {
    // roll back transaction
    $dbh->rollback();
    // log any errors to file
    ExceptionErrorHandler($e);
    require_once($footer_inc);
    exit;
}
我是PDO新手,上面可能有错误或问题,我还没有注意到,因为在我解决问题之前我还不能测试

1) 我需要知道如何首先在users表中插入users数据,以便获得MySQL提供给我的用户的uid

2) 然后获取其他表所需的uid

3) 但同时,如果查询在插入到users表后由于任何原因失败,那么数据也会从users表中删除

更新:


我更新了上面的代码以反映有用成员所做的更改。

此函数返回刚刚插入的记录的主键: 您需要它作为
need\u USERS\u UID\u for\u此处的
参数。在INSERT语句之后使用它


由于您启动了一个事务,如果您在MySQL表中使用InnoDB引擎(MyISAM不支持事务),则如果发生任何错误,数据将不会插入任何表中。

a)将
$dbh->beginTransaction()放入和try/catch块之外的前一行-在事务启动之前,不能回滚任何内容。b) 什么东西不适合这个?像往常一样使用lastInsertId。@Niko,我马上就做,谢谢phplover@Niko,我编辑了上面的代码以反映您所说的更改,我可以问一下为什么
$dbh->beginTransaction()是否也在try块中?我不太明白这一点,谢谢phplover只是检索ID,不使用它没有任何意义,对吗?应该是这样的:
$userId=$dbh->lastInsertId()-我不认为从try/catch块中调用beginTransaction()在大多数情况下都会导致问题,但如果启动事务失败并引发PDO异常,则应尝试在启动事务之前回滚事务。这导致了未定义的行为,很可能是一个新的错误。除此之外,你一切都很好。谢谢,我想我现在明白了,我把
$dbh->lastInsertId()在INSERT语句之后(参见原始帖子中编辑的代码),现在我按照您上面所说的得到了最后一个INSERT id,现在我如何访问最后一个INSERT id以将其放入其他查询
这里的NEED_USERS\u UID\u FOR
?对不起,我是PDO的新手,所以仍然在想这个问题,谢谢phploversorry,我想我可以更好地解释这个问题,我是否可以简单地为
$dbh->lastInsertId()分配一个变量$lastInsertID=$dbh->lastInsertID()
然后在此处显示
需要\u用户\u UID\u的位置
只需将其替换为
$lastInsertID
?谢谢,是的。只需将其存储为变量并在进一步查询中使用即可。如果交易失败,它将不会写入数据库。FractalizeR和Niko都提供了很好的答案,这对我很有帮助,很难选择一个可接受的答案,但因为FractalizeR是第一个回答的,并且会选择你的答案作为可接受的答案。谢谢你们两位的帮助,phplover,几分钟后我们会测试一下。