2012-04-14 31 views
29

私はサインアップページを持っており、基本的に私は4つのテーブルにデータを挿入する必要があります。私はPDOを初めて使い、何かに混乱しています。PHP PDOトランザクション?

基本的にいずれかの挿入が失敗した場合は、データベースに何も追加する必要はありません。

私の混乱は、最初にユーザーのユーザー名、電子メール、パスワードなどをusersテーブルに挿入する必要があるため、PDOを使ってMySQLが自分のユーザに与えたuid(mysqlによって増分される)を取得できます。他のテーブルにはuidが必要なので、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)私は私がUID MySQLは私のユーザーを与え得ることができるので、私は最初のユーザーテーブル内のユーザーデータを挿入する方法を知っておく必要があり

2)私は他のテーブルのためにそれを必要とするよう次にUIDを取得

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

UPDATE:

私が参考にメンバーによって提供された変更を反映するために上記のコードを更新しました。

+3

a) '$ dbh-> beginTransaction();'とその前の行をtry/catchブロックの外側に置きます。トランザクションが開始されるまで何もロールバックできません。 b)これと一緒に作業していないのは何ですか?いつものようにlastInsertIdを使用してください。 – Niko

+0

@Niko、私はこれを一瞬でやっていきます、あなたに感謝します。phplover – PHPLOVER

+0

@Niko、あなたが言った変更を反映するために上記のコードを編集しました。なぜ '$ dbh-> beginTransaction();' tryブロックも?ちょっと分かりません、ありがとう、phplover – PHPLOVER

答えて

18

この関数は、挿入されたレコードの主キーを返します。PDO::lastInsertId NEED_USERS_UID_FOR_HEREパラメータが必要です。 INSERT文の直後に使用してください。

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

+0

私はこれを理解していると思いますが、INSERTステートメントの後に '$ dbh-> lastInsertId();'を入れています(元の記事の編集コードを参照)。最後の挿入IDにアクセスして、他のクエリ 'NEED_USERS_UID_FOR_HERE'に挿入しますか?すみません、私はPDOに新しいので、まだそれを考え出して、感謝phplover – PHPLOVER

+0

申し訳ありませんが、私はちょっと説明することができます、単に変数を '$ dbh-> lastInsertId();'に代入すると '$ lastInsertID = $ dbh-> lastInsertId(); 'それから' NEED_USERS_UID_FOR_HERE'は '$ lastInsertID'で置き換えます。ありがとうphplover – PHPLOVER

+2

はい。変数として保存し、それ以降のクエリで使用するだけです。トランザクションが失敗した場合、データベースに書き込まれません。 –