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 :

Transaction PDO inactive [PDO]


Sujet :

PHP & Base de données

  1. #1
    Membre très actif
    Profil pro
    Inscrit en
    Février 2007
    Messages
    248
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 248
    Par défaut Transaction PDO inactive
    Bonjour,

    J'utilise PDO depuis un petit moment et je souhaiterai maintenant utiliser les transactions...

    J'initialise une transaction, effectue l'ensemble de mes traitements, lorsque je lance le commit() ou le rollback, j'ai l'exception avec le message suivant :'There is no active transaction'

    Je vous ai mis le code correspondant....
    (j'ai supprimé pas mal de ligne inutile et il ne s'agit que d'une portion d'un script, le nombre de } peut être erroné...)

    Merci d'avance !!!

    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
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
     
    // Debut de la transaction PDO 
    Factory::get( BDD_DRIVER ) -> beginTransaction() ;
     
    // Preparation des requetes PDO
    $preSelect 	= "SELECT note_valeur FROM etudiants_notes 
    			     WHERE note_etu_numero = :etu_numero 
    			     AND note_enseignement = '".$this -> idEns."' 
    			     AND note_epreuve = $epreuveId " ;
     
    $preUpdate	= "UPDATE etudiants_notes 
    			    SET note_valeur = :note
    			    WHERE note_etu_numero = :etu_numero 
    			    AND note_enseignement = '".$this -> idEns."' 
    			    AND note_epreuve = '$epreuveId' " ;
     
    $preInsert	= "INSERT INTO etudiants_notes 
    		    ( note_etu_numero , note_enseignement , note_epreuve , note_valeur )
    	            VALUES
    		    ( :etu_numero , '".$this -> idEns."' , '$epreuveId' , :note ) " ;
     
    $stmtSelect = Factory::get( BDD_DRIVER ) -> prepare( $preSelect ) ;
    $stmtUpdate = Factory::get( BDD_DRIVER ) -> prepare( $preUpdate ) ;
    $stmtInsert = Factory::get( BDD_DRIVER ) -> prepare( $preInsert ) ;
     
    // Ouverture du fichier en lecture
    ini_set( 'auto_detect_line_endings' , TRUE ) ;
    $csvContent = fopen( 'imports/'.$destinationName, 'r' ) ;
     
    // Traitement des donnees du fichier CSV
    while ( ( $data = fgetcsv( $csvContent, 20, ";" ) ) !== FALSE ) 
    {
        $this -> statistiques['nbNote']++ ;
     
        // Preparation des donnees 
        $numEtu = $data[0] ;
        $noteEtu = $data[1] ;
        $noteEtu = str_replace(',', '.', $noteEtu ) ; 
     
       // J'ai supprime les verifications sur le contenu
     
        if ( $this -> error == NULL )
        {
            // Verification si la note est deja saisie
    	$stmtSelect -> bindParam( ':etu_numero', $numEtu );
    	$stmtSelect -> execute();
    	$etuData	= $stmtSelect -> fetchAll( PDO::FETCH_ASSOC );
    	$etuOldNote = @$etuData[0]['note_valeur'] ;
    	$etuNb		= $stmtSelect -> rowCount() ;
     
    	// Insertion de la note
    	if ( $etuNb < 1 )
    	{
    		$stmtInsert -> bindParam( ':etu_numero', $numEtu );	
    		$stmtInsert -> bindParam( ':note', $noteEtu );
    		$stmtInsert -> execute() ;
    	}
    	// Mise a jour de la note
    	elseif ( $etuNb == 1 && $etuOldNote == '99.00' )
    	{
    		$stmtUpdate -> bindParam( ':etu_numero' , $numEtu ) ;
    		$stmtUpdate -> bindParam( ':note' , $noteEtu ) ;
    		$stmtUpdate -> execute();
    	}
     
            Factory::get( BDD_DRIVER ) -> commit() ;
        }
        else
        {
             Factory::get( BDD_DRIVER ) -> rollBack();
        }
    }
    }

  2. #2
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 49
    Par défaut
    Bonjour,

    Ça serait intéressant d'avoir le code de Factory.

    Le get () renvoie à chaque fois un objet basé sur la même connexion ouverte ?

  3. #3
    Membre très actif
    Profil pro
    Inscrit en
    Février 2007
    Messages
    248
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 248
    Par défaut
    C'est effectivement toujours la même connexion...

    Voici le code de la fonction get de factory...

    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
    class Factory 
    {
        static public function get( $sObject) 
        {
            if ( ! class_exists( $sObject)) 
            {
                if ( ! file_exists( $sFile = dirname( __FILE__).'/class.'.$sObject.'.php')) 
                {
                     throw new FactoryException( 'Driver introuvable.');
                }
                require $sFile;
                if ( ! class_exists( $sObject)) 
                {
                   throw new FactoryException( 'Driver mal implémenté');
                }
            }
            $oDriver = call_user_func( array( $sObject, 'getInstance'));
     
            return $oDriver;
        }

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 49
    Par défaut
    Ok.

    Je relis attentivement ton code.

    Ton commit et ton rollback sont dans un while, et ton beginTransaction est avant le while.

    Donc si tu itères au moins 2 fois, et bien la 2ème fois il n'y a plus de transaction ouverte...

    Par ailleurs, tu devrais garder ton objet dans une variable, plutôt que d'appeler le factory à tire-larigot. Même si le code du get n'a pas l'air très gourmand. D'autre part si tu décides de changer de manière de récupérer ta connexion, tu vas avoir un paquet de Factory::get... à rechercher / remplacer.

    [edit] Je ne suis toujours pas sur à 100% que tu as la même connexion à chaque fois, et ça n'est pas le code de Factory qui le prouve, la question est reportée sur la classe qui fournit le getInstance.
    Normalement, dans le pattern Factory, on a une instance différente chaque fois...

  5. #5
    Membre très actif
    Profil pro
    Inscrit en
    Février 2007
    Messages
    248
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 248
    Par défaut
    Ton commit et ton rollback sont dans un while, et ton beginTransaction est avant le while.
    Donc si tu itères au moins 2 fois, et bien la 2ème fois il n'y a plus de transaction ouverte...
    Merci bien pandrogynik, j'y crois pas d'être passé à coté de cette erreur !!

    Par ailleurs, tu devrais garder ton objet dans une variable, plutôt que d'appeler le factory à tire-larigot. Même si le code du get n'a pas l'air très gourmand. D'autre part si tu décides de changer de manière de récupérer ta connexion, tu vas avoir un paquet de Factory::get... à rechercher / remplacer.
    Je t'avoue que j'ai implémenté un factory sans maitriser vraiment la problématique... En tout cas, j'ai suivi ton conseil et j'ai placé l'objet dans un variable dans mon constructeur de class.

    Je ne suis pas toujours sur à 100% que tu as la même connexion à chaque fois, et ça n'est pas le code de Factory qui le prouve, la question est reportée sur la classe qui fournit le getInstance.
    Normalement, dans le pattern Factory, on a une instance différente chaque fois...
    Ah ben là, ce qui m'embête c'est que je renvoie à ma remarque précédente... j'aurai probablement mieux fait d'éviter d'utiliser factory que je ne maitrise pas ! Il faudrait vraiment que je me penche sur la question...

  6. #6
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 49
    Par défaut
    L'idée d'une factory (entre autre, ça n'est pas une définition exhaustive des enjeux de ce pattern), c'est souvent d'abstraire un choix de classe spécifique.

    C'est fréquent pour les classes de connexion BDD, on te propose d'identifier sous la forme d'un paramètre simple le driver utilisé ou le SGBD sollicité, ce qui permet une maintenance très simple en cas de changement de système, plutôt que d'avoir codé avec un "new" sur une classe du genre Driver_Pdo_JeNeSaisQuoi_Bidule_SQL_103b et de devoir changer pour MySQL_SuperPower_MegaConnector_Beta13.

    En revanche, il n'y est pas, en général ,question d'unicité d'instance. L'unicité nous amène à songer au pattern singleton, qui répond à des problématiques toutes autres. Il ne faut pas se laisser tromper par la méthode "getInstance" qui est par "tradition" le nom donné à la méthode statique permettant précisément de récupérer un singleton.

    Ton Factory ne présente pas de problème notable, et récupérer une fois seulement l'objet dans une variable sera finalement la meilleure garantie que tu causes toujours à la même connexion.

    Bonne chance pour la suite.

  7. #7
    Membre éprouvé Avatar de Cobaye
    Profil pro
    Développeur Web
    Inscrit en
    Décembre 2002
    Messages
    120
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2002
    Messages : 120
    Par défaut
    Il me semble que pour les transaction PDO fonctionnent, il faut que la base de données le supporte ou sous Mysql faut que les tables en InnoDb et non en Mysam.

  8. #8
    Membre très actif
    Profil pro
    Inscrit en
    Février 2007
    Messages
    248
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 248
    Par défaut
    L'idée d'une factory (entre autre, ça n'est pas une définition exhaustive des enjeux de ce pattern), c'est souvent d'abstraire un choix de classe spécifique.
    [...]
    En revanche, il n'y est pas, en général ,question d'unicité d'instance. L'unicité nous amène à songer au pattern singleton, qui répond à des problématiques toutes autres. Il ne faut pas se laisser tromper par la méthode "getInstance" qui est par "tradition" le nom donné à la méthode statique permettant précisément de récupérer un singleton.
    J'ai un singleton en place également... mais comme pour le factory, ce n'est pas vraiment ma tasse de thé, donc je ne m'aventurerai pas à dire que son implémentation est correcte...
    Néanmoins, tout semble fonctionner...

    Ton Factory ne présente pas de problème notable, et récupérer une fois seulement l'objet dans une variable sera finalement la meilleure garantie que tu causes toujours à la même connexion.
    Oui j'ai ajouté l'objet dans une variable au niveau du constructeur de classe comme tu me l'as conseillé (disons pour la variable, dans le constructeur c'est une initiative), néanmoins je crois que je vais avoir un soucis si je fais ça partout, car si j'instancie deux classes différentes...

    Bonne chance pour la suite.
    Merci bien en tout cas et au delà de la chance, va surtout falloir que je me penche sur les design pattern !

    Il me semble que pour les transaction PDO fonctionnent, il faut que la base de données le supporte ou sous Mysql faut que les tables en InnoDb et non en Mysam.
    Oui Cobaye, je confirme ! Les transactions fonctionnent très bien avec PDO. En innodb bien sûr, myisam ne supportant tout simplement pas les transaction...

  9. #9
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 49
    Par défaut
    Une variable au niveau de constructeur de la classe ? De quelle classe ? Le Factory ?

  10. #10
    Membre très actif
    Profil pro
    Inscrit en
    Février 2007
    Messages
    248
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 248
    Par défaut
    Non non pas dans le factory, dans une autre classe, celle que j'utilise pour la gestion des imports...

    C'est peut être pas une bonne idée...

  11. #11
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    49
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 49
    Par défaut
    Ah, ok. Je ne sais pas, tu fais comme tu veux, c'est juste que j'avais cru comprendre autre chose.

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

Discussions similaires

  1. [PDO] Transaction PDO mysql
    Par chat de nuit dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 25/10/2011, 16h33
  2. [MySQL] php pdo Transactions
    Par watibou dans le forum PHP & Base de données
    Réponses: 0
    Dernier message: 03/09/2010, 14h59
  3. [PDO] PDO et transactions
    Par Madfrix dans le forum PHP & Base de données
    Réponses: 6
    Dernier message: 10/05/2010, 08h21
  4. [PDO] PDO/MYSQL: les transactions?
    Par Helfima dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 21/04/2009, 10h04
  5. Apropos des Transactions au sein d'un Stored Procedure
    Par Sarbacane dans le forum Connexion aux bases de données
    Réponses: 6
    Dernier message: 16/11/2004, 08h21

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