2011-12-23 46 views
5

Tôi cố gắng để thiết lập giao dịch đầu tiên của tôi trong MySQL sử dụng PHP/PDO ...PHP PDO MySQL cấu trúc mã giao dịch

Tôi chỉ có một câu hỏi nhanh chóng, cách tốt nhất để xác định xem các truy vấn trước đó đã là gì thành công hay không? Đây là những gì tôi có ngay bây giờ, nhưng tôi thà tìm cách kiểm tra truy vấn bằng câu lệnh if.

Điều này là khá nhiều giả lập mã để cố gắng để có được một mô hình làm việc .. Tôi biết $ kết quả là không hiệu quả thử nghiệm nếu bất cứ điều gì là tốt hay xấu .. tôi có nó ở đó nhiều hơn như một nơi giữ cho thực sự đối phó khi thời gian đến ..

if ($_POST['groupID'] && is_numeric($_POST['groupID'])) { 
    $sql = "SET AUTOCOMMIT=0"; 
    $dbs = $dbo->prepare($sql); 
    $dbs->execute(); 

    $sql = "START TRANSACTION"; 
    $dbs = $dbo->prepare($sql); 
    $dbs->execute(); 

    $sql = "DELETE FROM users_priveleges WHERE GroupID=:groupID"; 
    $dbs = $dbo->prepare($sql); 
    $dbs->bindParam(":groupID", $_POST['groupID'], PDO::PARAM_INT); 
    $dbs->execute(); 

    try { 
     $sql = "DELETE FROM groups WHERE GroupID=:groupID LIMIT 1"; 
     $dbs = $dbo->prepare($sql); 
     $dbs->bindParam(":groupID", $_POST['groupID'], PDO::PARAM_INT); 
     $dbs->execute(); 

     $results["error"] = null; 
     $results["success"] = true; 

     try { 
      $sql = "DELETE FROM users WHERE Group=:groupID"; 
      $dbs = $dbo->prepare($sql); 
      $dbs->bindParam(":groupID", $_POST['groupID'], PDO::PARAM_INT); 
      $dbs->execute(); 

      $results["error"] = null; 
      $results["success"] = true; 

      $sql = "COMMIT"; 
      $dbs = $dbo->prepare($sql); 
      $dbs->execute(); 
     } 
     catch (PDOException $e) { 
      $sql = "ROLLBACK"; 
      $dbs = $dbo->prepare($sql); 
      $dbs->execute(); 

      $results["error"] = "Could not delete associated users! $e"; 
      $results["success"] = false; 
     } 
    } 
    catch (PDOException $e) 
    { 
     $sql = "ROLLBACK"; 
     $dbs = $dbo->prepare($sql); 
     $dbs->execute(); 

     $results["error"] = "COULD NOT REMOVE GROUP! $e"; 
     $results["success"] = false; 
    } 
} 
+2

Tại sao không sử dụng beginTransaction PDO của(), cam kết() và rollback() phương pháp? – GordonM

+0

LOL Tôi mới học về phương pháp beginTransaction sáng nay ... Tôi đã tìm ra hai người còn lại ở đó, nhưng vẫn chưa nhìn họ. Đó là trên danh sách TODO nhờ cảm ơn! – guyfromfl

+0

Ngoài ra, bạn không phải chuẩn bị() mọi tuyên bố, trên thực tế nó là lãng phí cho những người mà bạn sẽ không chèn bất kỳ biến nào. Chỉ cần chạy những người có truy vấn() để thay thế. Lưu trên cả hai dòng mã và chuẩn bị không cần thiết. – GordonM

Trả lời

3

execute() lợi nhuận PDO Bản tuyên Bố của TRUE trên thành công và FALSE về thất bại, vì vậy bạn có thể kiểm tra giá trị trả về của trước execute() trong câu lệnh if của bạn.

$pdo_result = $dbs->execute(); 
if ($pdo_result) { 
    // handle success 
} else { 
    // handle failure 
    // you can get error info with $dbs->errorInfo(); 
} 

Điều đó nói rằng, như @ Bill Kerwin một cách chính xác chỉ ra (trong câu trả lời của anh ấy rằng tôi hoàn toàn upvoting bởi vì nó chính xác là đúng), nó sẽ là thích hợp hơn để sử dụng PDO::beginTransaction(), PDO::commit(), và PDO::rollback().

+0

Làm cách nào để biết nguyên nhân gây ra lỗi? Tôi muốn làm cho nó đáp ứng với vấn đề. Xin lỗi giao dịch đầu tiên vẫn còn mới đối với PDO ... Cảm ơn bạn đã trả lời – guyfromfl

+1

'$ dbs-> errorInfo()' Xem tài liệu tại http://www.php.net/manual/en/pdostatement.errorinfo.php để được giải thích giá trị trả về của nó. – Trott

+0

cảm ơn đẹp ... – guyfromfl

6

Tôi sẽ không chuẩn bị & thực hiện các báo cáo giao dịch. Tôi muốn sử dụng PDO::beginTransaction(), PDO::commit()PDO::rollback().

PDO :: Prepare() và PDO :: execute() trả về SAI nếu có lỗi, nếu không chúng sẽ ném PDOException nếu bạn setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION).

Trong trình xử lý ngoại lệ, bạn nên kiểm tra PDO::errorInfo() và báo cáo bản chất của lỗi. Thực hành tốt nhất là ghi nhật ký thông tin lỗi thô, nhưng cung cấp cho người dùng một thông điệp thân thiện hơn.

Không lặp lại thông báo lỗi bằng chữ trong giao diện người dùng - điều này có thể cung cấp cho người dùng kiến ​​thức không phù hợp về truy vấn và lược đồ SQL của bạn.

+0

Tôi đã học về các phương thức giao dịch trước đó.Toàn bộ lý do tôi muốn kiểm soát nó với các câu lệnh nếu nó dễ dàng hơn, đối với tôi và kinh nghiệm hạn chế của tôi, để nắm bắt được lỗi cụ thể. Tôi cũng đọc rằng thử không phải là lý tưởng cho những gì tôi đang làm vì nhiều lý do. Cảm ơn bạn về thông tin. rất nhiều để xem xét! – guyfromfl

+0

Tôi chỉ cần kiểm tra lại, tùy chọn setAttribute được thiết lập để được thông qua khi tôi khởi tạo đối tượng $ dbo, vì vậy chúng tôi ở đó..thanks for the feed back – guyfromfl

20

Một số lưu ý chung: Không sử dụng bindParam() trừ khi bạn sử dụng quy trình sửa đổi giá trị của thông số Do đó, use bindValue(). bindParam() chấp nhận giá trị đối số như một biến được tham chiếu. Điều đó có nghĩa là bạn không thể làm $stmt->bindParam(':num', 1, PDO::PARAM_INT); - nó làm tăng lỗi. Ngoài ra, PDO có các chức năng riêng để kiểm soát các giao dịch, bạn không cần thực hiện các truy vấn theo cách thủ công.

Tôi viết lại mã của bạn một chút để làm sáng tỏ về cách PDO có thể được sử dụng:

if($_POST['groupID'] && is_numeric($_POST['groupID'])) 
{ 
    // List the SQL strings that you want to use 
    $sql['privileges'] = "DELETE FROM users_priveleges WHERE GroupID=:groupID"; 
    $sql['groups']  = "DELETE FROM groups WHERE GroupID=:groupID"; // You don't need LIMIT 1, GroupID should be unique (primary) so it's controlled by the DB 
    $sql['users']  = "DELETE FROM users WHERE Group=:groupID"; 

    // Start the transaction. PDO turns autocommit mode off depending on the driver, you don't need to implicitly say you want it off 
    $pdo->beginTransaction(); 

    try 
    { 
     // Prepare the statements 
     foreach($sql as $stmt_name => &$sql_command) 
     { 
      $stmt[$stmt_name] = $pdo->prepare($sql_command); 
     } 

     // Delete the privileges 
     $stmt['privileges']->bindValue(':groupID', $_POST['groupID'], PDO::PARAM_INT); 
     $stmt['privileges']->execute(); 

     // Delete the group 
     $stmt['groups']->bindValue(":groupID", $_POST['groupID'], PDO::PARAM_INT); 
     $stmt['groups']->execute(); 

     // Delete the user 
     $stmt['users']->bindParam(":groupID", $_POST['groupID'], PDO::PARAM_INT); 
     $stmt['users']->execute(); 

     $pdo->commit();  
    } 
    catch(PDOException $e) 
    { 
     $pdo->rollBack(); 

     // Report errors 
    }  
} 
+0

Wow cảm ơn vì thông tin bindParam/Value ... tất cả hướng dẫn PDO Tôi đã đọc đã sử dụng bindParam .. Mã đó trông tuyệt vời, tôi sẽ tinker với ý tưởng của bạn, làm cho rất nhiều ý nghĩa. – guyfromfl

+0

Tôi gặp lỗi khi cố xóa người dùng trong nhóm đó. Lỗi nói gần Group = 38 ... Hai truy vấn còn lại vẫn xóa các hàng khác trong các bảng khác, có vẻ giao dịch không hoạt động đúng cách ... – guyfromfl

+0

'GROUP' là một từ dành riêng cho SQL, vì vậy bạn có thể cần phải đặt nó trong dấu ngoặc kép. Nhưng nó sẽ là tốt hơn để đổi tên nó, vì vậy nó không phải là một từ dành riêng, và cũng vì vậy tất cả các bảng của bạn đặt tên nó 'GroupID' nhất quán. –