IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PHP & Base de données Discussion :

Relancer une transaction qui n'a pas fonctionné [PDO]


Sujet :

PHP & Base de données

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    530
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 530
    Points : 316
    Points
    316
    Par défaut Relancer une transaction qui n'a pas fonctionné
    Bonjour à tous,

    J'ai été confronté une fois à un problème qui ne s'est jamais reproduit et que je n'ai pas pu m'expliquer :

    Dans un programme de gestion de prestataire, plusieurs validations devaient être effectuées dans la BDD mais l'une d'elle ne s'est pas faite alors qu'elle était indiquée comme faite dans mon récapitulatif.

    alors micro coupure de l'alimentation du serveur distant ou autre raison je ne sais pas mais pour le cas que je suis en train de traiter en ce moment (validation d'une commande après retour d'information d'un paiement sécurisé) cela ne doit pas arriver.

    J'ai donc décidé d'utiliser une transaction avec gestion des erreurs.

    Par contre je me dis que si le problème décrit ci-dessus se reproduisait, je voudrais quand même que le programme ré-essaye de faire cette transaction pour essayer de la faire aboutir.

    Je limite le nombre d'essais à 5 parce que si ça n'a toujours pas marché au 5eme essai, inutile de faire une boucle à l'infini...

    au delà de 5 essais, l'erreur serait notée dans un fichier texte en recueillant un maximum d'informations pour permettre de retrouver le client sur l'interface du module de paiement sécurisé.

    voici donc ma fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    public function insertClient(){
     
    $this->BDD->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
     
    $this->BDD->beginTransaction();
     
    try{
     
    $query_inClient="INSERT INTO client SET ".$this->req;
    $this->BDD->exec($query_inClient);
    $this->IDClient=$this->BDD->lastInsertId();
     
    foreach($this->tabClient as $key=>$line){
    $this->req='IDClient='.$this->IDClient;
     
    foreach($line as $cle=>$valeur){
    $this->req.=", ".$cle."='".$valeur."'";
    };
     
    $query_inCommande="INSERT INTO client_commandes SET ".$this->req;
    echo $query_inCommande.'<br>';
    $this->BDD->exec($query_inCommande);
    };
     
    $tabTransac=array('trans_id','trans_date','card_brand','amount','auth_mode','auth_result','auth_number','warranty_result','payment_certificate','result');
    $this->req='';
     
    foreach($tabTransac as $element)$this->req.=$element."='".$this->{$element}."', ";
     
    $query_inTransac="INSERT INTO client_transactions SET ".$this->req."IDClient=".$this->IDClient;
    echo $query_inTransac.'<br>';
    $this->BDD->exec($query_inTransac);
    $this->IDTransac=$this->BDD->lastInsertId();
     
    $query_upTransac="UPDATE client SET transac=".$this->IDTransac." WHERE ID=".$this->IDClient;
    echo $query_upTransac.'<br>';
    $this->BDD->exec($query_upTransac);
     
    $this->BDD->commit();
     
    $this->suprTableProvisoir(); // fonction qui supprime les tables provisoire
     
    } catch(Exception $e){
    echo "ERREUR : ".$e->getMessage()."<br/>";
    $this->incremTest++;
    $this->BDD->rollBack();
    if($this->incremTest < 5) $this->insertClient(); 
    else {
     
    // écrire un message d'alerte dans un log
     
    }
     
    };
     
    }
    les echo me permettent de suivre ce qui se passe et j'ai volontairement introduit une erreur dans le nom de la table "client_transactions" en rajoutant un "s" pour voir ce qui se passe.

    et je récupère les erreur suivantes :

    INSERT INTO client_commandes SET IDClient=3, IDProd='4', nom='DDD', prenom='aaa', dateNaiss='2008-03-03', dateDu='2010-07-11', duree='7', tarif='125', remise='0', numClient='0_0'
    INSERT INTO client_transactions SET trans_id='073642', trans_date='20100324073642', card_brand='visa', amount='12500', auth_mode='FULL', auth_result='00', auth_number='587412', warranty_result='YES', payment_certificate='68969777322', result='00', IDClient=3
    ERREUR : SQLSTATE[42S02]: Base table or view not found: 1146 Table 'maBdd.client_transactions' doesn't exist
    ERREUR : SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
    ERREUR : SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
    ERREUR : SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
    ERREUR : SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
    on voit que les echo ne sont affichés qu'une fois et que l'erreur indiquée n'est plus la même, pourquoi ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if($this->incremTest < 5) $this->insertClient();
    cela ne devrait-il pas relancer toute l'exécution de ma fonction ?

    Quand j'aurais déjà compris ça, je verrai mieux si j'ai besoin de poser d'autres questions

    Merci d'avance pour vos réponses

  2. #2
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    83
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 83
    Points : 100
    Points
    100
    Par défaut Bonsoir
    Je pense que l'on peut en conclure que PDO::exec ne lève pas d'exception

    http://fr2.php.net/manual/fr/pdo.exec.php

    Sinon à la ligne $this->BDD->exec($query_inCommande);
    l'exception aurait été levée et jamais les lignes suivantes n'auraient été exécutée

    lors d'un levée d'exception, le code dans le try s'arrête et part directement dans le catch

    la bonne façon de faire serait :

    if( ! $this->BDD->exec($query_inCommande) )
    throw new Exception('QUERY_FAILED') ;

    pour bien lancer l'exception et partir dans le catch pour ainsi invalider la transaction et relancer la fonction.

    Xavier

  3. #3
    Membre expert Avatar de RunCodePhp
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    2 962
    Détails du profil
    Informations personnelles :
    Localisation : Réunion

    Informations forums :
    Inscription : Janvier 2010
    Messages : 2 962
    Points : 3 947
    Points
    3 947
    Par défaut
    Je pense que l'on peut en conclure que PDO::exec ne lève pas d'exception
    Exacte, tu as un problème, PDO normalement devrait déclencher une erreur étant donné que tu le défini avec le setAttribute().

    Peut être faudrait le définir bien avant, pas dans la méthode insertClient(), mais juste après avoir instancié PDO.
    Ou alors, au lieu de faire référence à la classe PDO, peut être faudrait il faire référence à ta classe PDO : (sans aucune garantie)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    $this->BDD->setAttribute(BDD::ATTR_ERRMODE, BDD::ERRMODE_EXCEPTION);
    if( ! $this->BDD->exec($query_inCommande) )
    throw new Exception('QUERY_FAILED');
    Si on défini que PDO doit lever une exception avec le setAttribute(), l'exception sera levée avant cette condition. Du coup, cette exception (QUERY_FAILED) sera inopérante.
    Enfin, normalement.

    Puis ne faudrait il pas utiliser PDOException au lieu de Exception ?
    Win XP | WampServer 2.2d | Apache 2.2.21 | Php 5.3.10 | MySQL 5.5.20
    Si debugger, c'est supprimer des bugs, alors programmer ne peut être que les ajouter [Edsger Dijkstra]

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    83
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 83
    Points : 100
    Points
    100
    Par défaut ca serait mieux
    tout à fait, respectons les docs

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Une formule qui ne veut pas fonctionner
    Par Maxence45 dans le forum Excel
    Réponses: 4
    Dernier message: 09/11/2007, 01h17
  2. Réponses: 3
    Dernier message: 01/06/2006, 16h26
  3. Réponses: 8
    Dernier message: 26/01/2006, 14h47
  4. lien pour une table qui ne doit pas etre public
    Par raslain dans le forum Oracle
    Réponses: 1
    Dernier message: 12/12/2005, 13h40
  5. Une requête qui ne reconnait pas is not null
    Par LeBauw dans le forum Access
    Réponses: 2
    Dernier message: 08/09/2005, 12h29

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo