2017-03-10 4 views
1

Si j'ai plusieurs requêtes sur la chaîne, sur une structure basée sur FI, comme ceci:requêtes MySQL Restauration d'

$query1 = mysqli_query("query here"); 

if(!query1){ 
    //display error 
} else { 
    $query2 = mysqli_query("another query here"); 
    if(!query2){ 
     //display error 
     //rollback the query1 
    } else { 
     query3 = mysqli_query("yet again another query"); 
     if(!query3) { 
      //display error 
      //rollback the query2 
      //rollback the query1 
     } else { 
      query4 = mysqli_query("eh.. another one"); 
      if(!query4){ 
       //display error 
       //rollback the query3 
       //rollback the query2 
       //rollback the query1 
      } else { 
       return success; 
      } 
     } 
    } 
} 

Y at-il une meilleure façon de rollback la requête précédente, si le prochain échoue? Sinon, je vais avoir la première requête 2 succès, qui a édité la base de données, mais le 3 ° a échoué, donc 3 ° et 4 ° n'a pas édité la dabatase, avec le résultat de l'avoir corrompu.

Je pensais à quelque chose comme:

... 
    $query2 = mysqli_query("another query here"); 
    if(!query2){ 
     //display error 
     $rollback = mysqli_query("query to rollback query1"); 
    } else { 
     query3 = mysqli_query("yet again another query"); 
     if(!query3) { 
      //display error 
      $rollback = mysqli_query("query to rollback query2"); 
      $rollback = mysqli_query("query to rollback query1"); 
     } else { 
     ... 

Mais les subventions de la méthode ci-dessus encore plus de chances d'échouer plus de requêtes. Existe-t-il d'autres méthodes plus efficaces?

+0

Pour « rollback » une requête, utilisez begin tran premier et l'utilisation de validation ou l'annulation, je vous conseille de chercher transactions – Rhopercy

+0

Comment exactement je fais ça? une référence/un guide? –

+0

Vous pouvez commencer ici: https://dev.mysql.com/doc/refman/5.7/en/commit.html – Rhopercy

Répondre

2

Voici comment je le ferais avec mysqli:

Configurer mysqli (somewehere au début de l'application) pour lancer des exceptions lorsqu'une requête échoue.

mysqli_report(MYSQLI_REPORT_STRICT); 

De cette façon, vous n'aurez pas besoin de tous les if .. elseif .. else.

$connection->begin_transaction(); 
try { 
    $result1 = $connection->query("query 1"); 
    // do something with $result1 

    $result2 = $connection->query("query 2"); 
    // do something with $result2 

    $result3 = $connection->query("query 3"); 
    // do something with $result3 

    // you will not get here if any of the queries fails 
    $connection->commit(); 
} catch (Exception $e) { 
    // if any of the queries fails, the following code will be executed 
    $connection->rollback(); // roll back everything to the point of begin_transaction() 
    // do other stuff to handle the error 
} 

Mise à jour

Habituellement, l'utilisateur ne se soucient pas, pourquoi son action a échoué. Si une requête échoue, ce n'est jamais la faute des utilisateurs. C'est soit la faute du développeur ou de l'environnement. Il ne devrait donc pas y avoir de raison de rendre un message d'erreur en fonction de la requête qui a échoué.

Notez que si les utilisateurs est intput la source de la requête a échoué, puis

  1. vous ne validait pas correctement l'entrée
  2. vos requêtes ne sont pas injection sûr (Si l'entrée peut provoquer une SQL erreur, il peut également être utilisé pour compromettre votre DB.)

Cependant - je ne dis pas qu'il n'y a pas de raisons - je n'en sais tout simplement pas. Donc, si vous voulez que votre message d'erreur dépendent de la requête a échoué, vous pouvez effectuer les opérations suivantes:

$error = null; 
$connection->begin_transaction(); 
try { 
    try { 
     $result1 = $connection->query("query 1"); 
    } catch (Exception $e) { 
     $error = 'query 1 failed'; 
     throw $e; 
    } 
    // do something with $result1 

    try { 
     $result2 = $connection->query("query 2"); 
    } catch (Exception $e) { 
     $error = 'query 2 failed'; 
     throw $e; 
    } 
    // do something with $result2 

    // execute more queries the same way 

    $connection->commit(); 
} catch (Exception $e) { 
    $connection->rollback(); 
    // use $error to find out which query failed 
    // do other stuff to handle the error 
} 
+0

Mmm c'est intéressant, mais, comment puis-je savoir sur l'exception si elle échoue le résultat 2 au lieu de 1 par exemple? –

+0

@NetJacker Vous ne le connaissez pas à l'exécution. Cela suit la règle "tout ou rien". Si quelque chose échoue, annulez tous les changements. Vous pouvez analyser le message d'erreur dans le journal des erreurs plus tard et corriger la source de l'erreur. –

+0

Ceci est la bonne réponse. Vous n'avez pas besoin de savoir quelle requête a échoué, mais vous aurez depuis l'exception contiendra le message à propos de l'erreur. C'est la bonne façon et donc +1 de moi. –