2012-04-14 41 views
29

Tôi có một trang đăng ký và về cơ bản tôi cần dữ liệu được chèn vào 4 bảng. Tôi mới đến PDO và đang bối rối về điều gì đó.Giao dịch PDO PHP?

Về cơ bản nếu bất kỳ chèn nào không thành công, tôi không muốn bất kỳ thứ gì được thêm vào cơ sở dữ liệu, điều đó dường như đủ đơn giản.

Sự nhầm lẫn của tôi là, trước tiên tôi cần chèn tên người dùng, email, mật khẩu, v.v. vào bảng users để tôi có thể nhận được (không biết chắc) bằng cách sử dụng PDO mà uid MySQL đã cung cấp cho người dùng của tôi (tự động tăng lên bởi mysql). Tôi cần người dùng uid MySQL đã cho người dùng của tôi cho các bảng khác như các bảng khác cần uid để tất cả mọi thứ được liên kết đúng với nhau. Bảng của tôi là InnoDB và tôi có khóa ngoài từ users_profiles (user_uid), users_status (user_uid), users_roles (user_uid) đến users.user_uid để chúng được liên kết với nhau.

Nhưng đồng thời tôi muốn đảm bảo rằng nếu ví dụ sau khi dữ liệu được chèn vào bảng users (vì vậy tôi có thể nhận được uid MySQL đã cung cấp cho người dùng) rằng nếu bất kỳ chèn nào khác không thể xóa dữ liệu đã được đưa vào bảng users.

Tôi nghĩ tốt nhất là tôi nên hiển thị mã của mình; Tôi đã nhận xét ra mã và đã giải thích trong mã mà có thể làm cho nó dễ hiểu hơn.

// 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; 
} 

Tôi mới tham gia PDO và có thể có lỗi hoặc vấn đề ở trên mà tôi chưa thông báo vì tôi chưa thể kiểm tra cho đến khi tôi tìm ra vấn đề của mình.

1) Tôi cần phải biết làm thế nào tôi có thể chèn dữ liệu người dùng trong bảng người dùng đầu tiên vì vậy tôi có thể nhận được MySQL uid cho người dùng của tôi

2) Sau đó lấy uid như tôi cần nó cho các bảng khác

3) Nhưng đồng thời nếu truy vấn không thành công vì bất kỳ lý do nào sau khi chèn vào bảng người dùng thì dữ liệu cũng sẽ bị xóa khỏi bảng người dùng.

UPDATE:

tôi cập nhật mã trên để phản ánh những thay đổi đã được cung cấp bởi các thành viên hữu ích.

+3

a) Đặt '$ dbh-> beginTransaction();' và dòng trước đó bên ngoài khối try/catch - bạn không thể khôi phục bất kỳ thứ gì cho đến khi giao dịch được bắt đầu. b) Điều gì không làm việc với điều này? Chỉ cần sử dụng lastInsertId như bình thường. – Niko

+0

@Niko, tôi sẽ thực hiện việc này trong giây lát, cảm ơn bạn phplover – PHPLOVER

+0

@Niko, tôi đã chỉnh sửa mã ở trên để phản ánh thay đổi bạn đã nói, tôi có thể hỏi tại sao không thể '$ dbh-> beginTransaction();' khối thử cũng? không hoàn toàn hiểu rằng bit, nhờ phplover – PHPLOVER

Trả lời

18

Chức năng này trả về khóa chính của bản ghi vừa được chèn: PDO::lastInsertId Bạn sẽ cần nó cho tham số NEED_USERS_UID_FOR_HERE. Sử dụng nó ngay sau khi phát biểu INSERT.

Vì bạn đã bắt đầu giao dịch, dữ liệu sẽ không được chèn vào bất kỳ bảng nào nếu có lỗi xảy ra khi bạn sử dụng công cụ InnoDB cho bảng MySQL của bạn (MyISAM không hỗ trợ giao dịch).

+0

cảm ơn tôi nghĩ rằng tôi đang hiểu nó bây giờ, tôi đặt '$ dbh-> lastInsertId();' sau câu lệnh INSERT (xem mã đã chỉnh sửa trong bài gốc), bây giờ tôi có id chèn cuối cùng làm những gì bạn đã nói ở trên, cách tôi có truy cập id chèn cuối cùng để đặt nó trong các truy vấn khác 'NEED_USERS_UID_FOR_HERE' không? xin lỗi im mới để PDO vì vậy vẫn còn figuring nó ra, nhờ phplover – PHPLOVER

+0

xin lỗi nghĩ rằng tôi có thể giải thích rằng bit tốt hơn, tôi chỉ cần chỉ định một biến '$ dbh-> lastInsertId();' để nó trở thành một cái gì đó như '$ lastInsertID = $ dbh-> lastInsertId(); 'và sau đó ở đâu nó nói' NEED_USERS_UID_FOR_HERE' chỉ thay thế bằng '$ lastInsertID'? cảm ơn phplover – PHPLOVER

+2

Có. Chỉ lưu trữ nó dưới dạng biến và sử dụng nó trong các truy vấn khác. Nó sẽ không được ghi vào cơ sở dữ liệu nếu giao dịch thất bại. –