web-dev-qa-db-ja.com

PHP PDOトランザクション?

サインアップページがあり、基本的には4つのテーブルにデータを挿入する必要があります。私はPDOを始めたばかりで、何かに戸惑っています。

基本的に、いずれかの挿入が失敗した場合、データベースに何も追加したくないので、それは十分に簡単に思えます。

私の混乱は、最初にユーザーのユーザー名、電子メール、パスワードなどをusersテーブルに挿入する必要があるため、PDOを使用して(MySQLによってmysqlによって自動インクリメントされた)UID MySQLがユーザーに与えたPDOを使用して取得できます。他のテーブルはすべてが適切にリンクされるようにuidを必要とするので、MySQLは他のテーブルのためにMySQLがユーザーにユーザーに与えたユーザーが必要です。私のテーブルはInnoDBであり、users_profiles(user_uid)、users_status(user_uid)、users_roles(user_uid)からusers.user_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)MySQLがユーザーに与えたuid MySQLを取得できるように、ユーザーテーブルにユーザーデータを最初に挿入する方法を知る必要があります

2)次に、他のテーブルに必要なuidを取得します

3)しかし、同時に、ユーザーテーブルに挿入した後、なんらかの理由でクエリが失敗した場合、データもユーザーテーブルから削除されます。

更新:

上記のコードを更新して、役立つメンバーから提供された変更を反映させました。

36
PHPLOVER

この関数は、挿入されたばかりのレコードの主キーを返します。 PDO :: lastInsertIdNEED_USERS_UID_FOR_HEREパラメータ。 INSERTステートメントの直後に使用します。

トランザクションを開始したため、MySQLテーブルにInnoDBエンジンを使用している場合、エラーが発生してもデータはテーブルに挿入されません(MyISAMはトランザクションをサポートしていません)。

18