2011-12-23 10 views
5

Próbuję skonfigurować swoją pierwszą transakcję w MySQL za pomocą PHP/PDO ...PHP PDO MySQL struktura Kod transakcji

mam tylko krótkie pytanie, co jest najlepszym sposobem, aby ustalić, czy poprzednie zapytanie było udane czy nie? Oto, co mam teraz, ale wolałbym znaleźć sposób na przetestowanie zapytania za pomocą instrukcji if.

To jest prawie makiety kod, aby spróbować uzyskać działający model .. Wiem, że wyniki $ nie jest skuteczne testowanie, jeśli coś było dobre lub złe .. mam go tam bardziej jako miejsce na prawdziwą ofertę kiedy przyjdzie czas ..

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

Dlaczego nie skorzystać z PDO beginTransaction(), commit() i rollback() metody? – GordonM

+0

LOL Właśnie dowiedziałem się dziś rano o metodzie beginTransaction ... Pomyślałem, że tamci dwaj pozostali, ale jeszcze ich nie odkryli. To jest na liście TODO tho dzięki! – guyfromfl

+0

Ponadto, nie musisz przygotowywać() każdego polecenia, w rzeczywistości jest to raczej marnotrawstwo dla tych, do których nie wstawisz żadnych zmiennych. Po prostu uruchom te z query(). Zapisuje zarówno linie kodu, jak i niepotrzebne przygotowania. – GordonM

Odpowiedz

3

PDO komunikat za execute() Zwraca TRUE w przypadku sukcesu, FALSE w przypadku porażki, dzięki czemu można przetestować zwracanej wartości z poprzedniego execute() w if.

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

Powiedział, że jak słusznie @Bill Kerwin się (w swojej odpowiedzi, że jestem całkowicie upvoting bo to dokładnie poprawne), lepiej byłoby użyć PDO::beginTransaction(), PDO::commit() i PDO::rollback().

+0

Skąd mam wiedzieć, co spowodowało błąd? Chciałbym, aby reagował na problem. Przepraszam, pierwsza transakcja wciąż jest nowa dla PDO ... Dzięki za odpowiedź – guyfromfl

+1

'$ dbs-> errorInfo()' Zobacz dokumentację na http://www.php.net/manual/en/pdostatement.errorinfo.php dla wyjaśnienia jego wartości zwrotnej. – Trott

+0

piękne dzięki ... – guyfromfl

6

Nie będę przygotowywać & do wykonywania transakcji transakcji. Użyłbym PDO::beginTransaction(), PDO::commit() i PDO::rollback().

PDO :: przygotować() i PDO :: execute() zwróci FALSE, jeśli wystąpi błąd, lub też wyrzucą wyjątek PDOException, jeśli jesteś setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION).

W programie obsługi wyjątku należy sprawdzić PDO::errorInfo() i podać charakter błędu. Najlepszą praktyką jest rejestrowanie surowych informacji o błędzie, ale przekazanie użytkownikowi bardziej przyjaznego komunikatu.

Nie powtarzaj dosłownego komunikatu o błędzie w interfejsie użytkownika - może to dać użytkownikowi niewłaściwą wiedzę na temat zapytania SQL i schematu.

+0

Tak właśnie dowiedziałem się wcześniej o metodach transakcji.Cały powód, dla którego chciałem kontrolować to stwierdzeniami, jest łatwiejsze, dla mnie i mojego ograniczonego doświadczenia, uchwycić konkretny błąd. Czytałem też, że try nie są idealne do tego, co robię z różnych powodów. Dzięki za informację. dużo do zobaczenia! – guyfromfl

+0

Po prostu podwójnie sprawdziłem, opcja setAttribute jest ustawiona na przekazanie, gdy uruchamiam obiekt $ dbo, więc jesteśmy dobrzy. Dzięki za informacje zwrotne – guyfromfl

20

Kilka uwag: Nie używaj bindParam() chyba zastosować procedurę, która modyfikuje wartość parametru Dlatego use bindValue(). bindParam() przyjmuje wartość argumentu jako zmienną referencyjną. Oznacza to, że nie możesz wykonać $stmt->bindParam(':num', 1, PDO::PARAM_INT); - powoduje to błąd. Ponadto PDO ma swoje własne funkcje do kontrolowania transakcji, nie trzeba wykonywać kwerend ręcznie.

przepisałem kod nieznacznie rzucić światło na sposób PDO można stosować:

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 dzięki za informacje bindParam/Value ... wszystkie samouczki PDO Czytałem, że użyłem bindParam. Ten kod wygląda świetnie, będę majstrował przy twoich pomysłach, robi dużo sensu. – guyfromfl

+0

Występuje błąd podczas próby usunięcia użytkowników z tej grupy. Błąd występuje w pobliżu grupy = 38 ... Pozostałe dwa zapytania nadal usuwają pozostałe wiersze z innych tabel, wydaje się, że transakcja nie działa poprawnie ... – guyfromfl

+0

'GROUP' jest słowem zastrzeżonym SQL, więc być może trzeba będzie umieścić to w back-quotes. Ale lepiej będzie zmienić nazwę, więc nie jest to słowo zarezerwowane, a także, że wszystkie twoje tabele nazywają to "GroupID" konsekwentnie. –