2012-04-14 140 views
29

我有一個註冊頁面,基本上我需要將數據插入到4個表格中。我是PDO的新手,對某事感到困惑。PHP PDO交易?

基本上,如果任何插入失敗我不希望任何添加到數據庫中,這似乎很簡單。我需要先在我的users表中插入用戶名,電子郵件,密碼等,這樣我就可以(不知道如何)使用PDO的uid MySQL給我的用戶(由mysql自動遞增)。我需要用戶uid MySQL爲其他表格提供我的用戶,因爲其他表格需要uid,所以一切都正確鏈接在一起。我的表是InnoDB,我的外鍵從users_profiles(user_uid),users_status(user_uid),users_roles(user_uid)到users.user_uid,因此它們都鏈接在一起。

但同時我想確保如果例如在users表中插入數據後(所以我可以得到uid MySQL給予的用戶),如果任何其他插入失敗,它會刪除數據被插入到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 2012-04-14 18:04:01

+0

@Niko,我會在一瞬間做到這一點,謝謝phplover – PHPLOVER 2012-04-14 18:13:57

+0

@Niko,我編輯了上面的代碼來反映你說的改變,我可以問爲什麼不能'$ dbh-> beginTransaction();'在try塊也是?不太明白這一點,謝謝phplover – PHPLOVER 2012-04-14 18:23:41

回答

18

該函數返回剛剛插入記錄的主鍵:PDO::lastInsertId 您將需要它爲NEED_USERS_UID_FOR_HERE參數。在INSERT語句後使用它。

由於您啓動了一個事務,如果您的MySQL表使用InnoDB引擎(MyISAM不支持事務),如果發生任何錯誤,數據將不會插入到任何表中。

+0

感謝我認爲我現在瞭解它,我把'dbh-> lastInsertId();'在INSERT語句後面(請參閱原始文章中的編輯代碼),現在我得到了最後一個insert id,現在,我是否可以訪問最後一個插入ID來將其放入其他查詢'NEED_USERS_UID_FOR_HERE'?對不起,即使新的PDO,所以仍然搞清楚,謝謝phplover – PHPLOVER 2012-04-14 18:16:57

+0

抱歉,我認爲我可以更好地解釋一下,我只是簡單地分配一個變量到'$ dbh-> lastInsertId();'因此它變得像'$ lastInsertID = $ dbh-> lastInsertId();'然後它說'NEED_USERS_UID_FOR_HERE'只是用'$ lastInsertID'替換它?謝謝phplover – PHPLOVER 2012-04-14 18:26:33

+2

是的。只需將其存儲爲一個變量並將其用於進一步查詢。如果事務失敗,它將不會寫入數據庫。 – 2012-04-14 18:28:37