LastInsertId

Résolu
Bonjour Après utilisation de la méthode last_insert_id() de PDO je n'arrive pas a comprendre pourquoi je ne recupère pas le dernier idrep et donc ma deuxième requête ne s'insere pas, pouvez vous m'aider s'ils vous plait je vous remercie
	switch($_POST['haction']) {

		case 'new':
			$requete = "INSERT INTO cdc_repetitions (drepet) VALUES ('$drepet')";
			$typenr = "enregistré";
			$reqaj = $requete; 
			$resultat = executeQuery($requete,$bdd);
			
			$idrep = $bdd->lastInsertId();
			$presents = isset($_POST['presents']) ? $_POST['presents'] : NULL;
			
		if (is_array($presents)) {	
		    foreach($presents as $idpers) {
			
			$requete = "INSERT INTO cdc_assister (idpers,idrep,idloc) VALUES ('$idpers','$idrep','$idloc')";
			$typenr = "enregistré"; 
			$reqaj = $requete; 
			$resultat = executeQuery($requete,$bdd); 
		    }
		}
			$success = "<span class='success'>Les présences à la répétition - ".trim(stripslashes(" du " . dateFR("$drepet")))." - a été $typenr.</span>";
			break;
	}

Lorsque je fait $idrep = mysql_insert_id(); au lieu de $idrep = $bdd->lastInsertId(); la deuxième requète n'insere pas $idrep

16 réponses

Résumé de la discussion

Le problème porte sur la récupération du dernier identifiant inséré avec PDO après une insertion et son utilisation pour enregistrer des lignes liées dans une seconde requête. Des réponses suggèrent de récupérer l'id immédiatement après l'insertion et d'utiliser une fonction dédiée qui renvoie cet identifiant, plutôt que de s'appuyer sur mysql_insert_id ou lastInsertId isolément. Certaines explications soulignent aussi des erreurs avec des fetch/foreach et des appels à fetchAll ou fetchColumn, recommandant l'usage de requêtes préparées et d'assigner les paramètres de manière explicite. En pratique, cela nécessite soit de faire insérer chaque ligne séparément avec l'id obtenu, soit de retourner l'id depuis la fonction d'insertion et de l'utiliser pour toutes les insertions suivantes.

Bobot (l’IA à votre service)
  1. jdoodle.sh: line 1: syntax error near unexpected token `$_POST['haction']'
    jdoodle.sh: line 1: `switch($_POST['haction']) {'
    0
    1. Modérateur
      Il nous faut le reste du code dr cette page.
      0
  2. Bonjour
    $action = 'new';                     
    if($_GET['a']) { $a = $_GET['a']; }  
    if(isset($_GET['idrep'])) { $idrep = $_GET['idrep']; }
    
    switch($a) {
    	case 'new': $action = 'new';  break; 
    	default   : $action = 'new';  break;
    }
    
    if($_POST['submit']) {
    
    	$idrep		= $_POST['idrep'];
        $drepet     = dw2m($_POST['drepet']);
    	$idpers  	= $_POST['idpers'];
    	$idloc  	= $_POST['idloc'];
    
    	switch($_POST['haction']) {
    		case 'new':
    			$requete = "INSERT INTO cdc_repetitions (drepet) VALUES ('$drepet')";
    			$typenr = "enregistré";
    			$reqaj = $requete; 
    			$resultat = executeQuery($requete,$bdd);
    			
    			$idrep = $bdd->lastInsertId();
    			$presents = isset($_POST['presents']) ? $_POST['presents'] : NULL;
    			
    		if (is_array($presents)) {	
    		    foreach($presents as $idpers) {
    			
    			$requete = "INSERT INTO cdc_assister (idpers,idrep,idloc) VALUES ('$idpers','$idrep','$idloc')";
    			$typenr = "enregistré"; 
    			$reqaj = $requete; 
    			$resultat = executeQuery($requete,$bdd); 
    		    }
    		}
    			$success = "<span class='success'>Les présences à la répétition - ".trim(stripslashes(" du " . dateFR("$drepet")))." - a été $typenr.</span>";
    			break;
    	}
    }
    
    switch($action) {
    	case 'new':
    		$title	= "Saisie des présences aux répétitions"; 
    		$btsub	= "Enregistrer";
    		$idrep	= "";
    		$drepet	= "";
    		$idpers	= "";
    		$idloc	= 1;
    		break;
    }
    
    0
  3. Bonjour
    La fonction est dans mon fichier init.php que j'appelledans la page de mon script.
    // Fonction qui sert à faire les requêtes SQL
    function executeQuery($requete,$bdd) {
    	$bdd = bdd();	
    	//exécution de la requête
    	try {
    		$resultat = $bdd->prepare($requete);
    		$resultat->execute();
    	} catch(Exception $e) {
    	// en cas d'erreur :
    		echo " Erreur ! ".$e->getMessage();
    		exit(0); // en cas d'erreur.. arrête le script !
    	}
    	return $resultat;
    }
    
    0
    1. Modérateur
      Tu as changé $datas par $bdd.... Pourquoi ?
      0
  4. En fait après l'utilisation de la méthode lastinsertid() de PDO cela me retourne pas l'identifiant $idrep.
    pPr contre j'ai bien en début de ma page la gestion des erreurs, cela me retourne quelques notice variable non défini mais rien qui corresponds à mon soucis.
    0
    1. Modérateur
      Je te propose d'utiliser ces 3 fonctions.
      Chacune servant à des types de requêtes spécifiques
      
      
      /** Fonction qui sert à faire les requêtes SELECT SQL (UNIQUEMENT)
      * @$requete string : requête SQL à effectuer
      * @datas array contenant les éventuelles variables à passer à la requête
      * return array : retourne un Array contenant le résultat du select
      */
      function dbSelect($requete,$datas=NULL) {
       $bdd = bdd(); 
       //exécution de la requête
       try {
        $prep = $bdd->prepare($requete);
        $prep->execute($datas);
        $result = $prep->fetchAll();
       } catch(Exception $e) {
       // en cas d'erreur :
        echo " Erreur ! ".$e->getMessage();
        exit(0); // en cas d'erreur.. arrête le script !
       }
       return $result;
      }
      
      /** Fonction qui sert à faire les requêtes DELETE / UPDATE (UNIQUEMENT)
      * @$requete string : requête SQL à effectuer
      * @datas array contenant les éventuelles variables à passer à la requête
      * return int : retourne le nombre de lignes impactées par la requête
      */
      function dbExec($requete,$datas=NULL) {
       $bdd = bdd(); 
       //exécution de la requête
       try {
        $prep = $bdd->prepare($requete);
        $prep->execute($datas);
        $resultat = $prep->rowCount();
       } catch(Exception $e) {
       // en cas d'erreur :
        echo " Erreur ! ".$e->getMessage();
        exit(0); // en cas d'erreur.. arrête le script !
       }
       return $resultat;
      }
      
      /** Fonction qui sert à faire les requêtes INSERT (UNIQUEMENT)
      * @$requete string : requête SQL à effectuer
      * @datas array contenant les éventuelles variables à passer à la requête
      * return int : retourne le "LastId" généré par l'insert
      */
      function dbInsert($requete,$datas=NULL) {
       $bdd = bdd(); 
       //exécution de la requête
       try {
        $prep = $bdd->prepare($requete);
        $prep->execute($datas);
        $resultat = $bdd->lastInsertId();
       } catch(Exception $e) {
       // en cas d'erreur :
        echo " Erreur ! ".$e->getMessage();
        exit(0); // en cas d'erreur.. arrête le script !
       }
       return $resultat;
      }
      


      ce qui, pour ton code actuel, se traduirait par :
      case 'new':
       $requete = "INSERT INTO cdc_repetitions (drepet) VALUES (:drepet)";
       $datas = array(':drepet'=>$drepet);
       $idrep = dbInsert($requete,$datas);
       $typenr = "enregistré";
       $reqaj = $requete; 
          
       $presents = isset($_POST['presents']) ? $_POST['presents'] : NULL;
      


      0
      1. J'ai une erreur qui correspond à la fonction dbSelect
        Fatal error: Call to a member function fetchAll() on boolean in /home/cliquede/admin/libs/init.php on line 52
        
        0
        1. Modérateur
          Petite erreur :
          $result = $res->fetchAll();
          


          A remplacer par :
          $result = $prep->fetchAll();
          


          J'édite mon code précédent pour l'y corriger également.
          0
      2. Maintenant que j'ai les fonctions pour faire mes requêtes tu peux me donner un exemple d'une requête SELECT s'il te plait.
        0
        1. Modérateur
          $sql = "SELECT n.numero 
                      FROM cdc_numerotation N left join cdc_interpreter I on N.idnum=I.idnum
          WHERE I.idnum is null"; 
          $datas = NULL; //pas de variable à passer pour cette requête la...
          $array_result = dbSelect($sql,$datas);
          
          //on affiche le résultat de la requete
          print_r($array_result);
          
          //ou via une boucle par exemple :
          foreach ($array_result as $R){
            echo $R['numero'];
          }
          
          0
        2. J'ai cette erreur
          Fatal error: Call to a member function fetch() on array in
          

          avec cette requète

          $requete = "SELECT * FROM $cfg";
          $datas = NULL;
          $config = dbSelect($requete,$datas);
          while ($donnees = $config->fetch()) { ${$donnees->clef} = $donnees->valeur; }
          0
        3. Modérateur
          @LaChaux78Normal ... vu que tu n'as pas regardé le code que je t'ai donné
          remplace ton while par :
          //ou via une boucle par exemple :
          foreach ($configas as $donnees){
            ${$donnees->clef} = $donnees->valeur
          }


          PS: ... au passage .....j'aimerai bien qu'un jour... tu te mettes enfin à utiliser la COLORATION SYNTAXIQUE lorsque tu postes du code sur le forum... pour ça... rien de plus simple... il suffit de préciser le LANGAGE dans les balises de code.
          Explications disponibles ici : https://codes-sources.commentcamarche.net/faq/10686-le-nouveau-codes-sources-comment-ca-marche#balises-code
          0
      3. Bonjour,
        Maintenant j'ai un autre soucis sur une requête SELECT avec la fonction rowCount.
        Cela me permet de rechercher le timestamp de la dernière sauvegarde de ma BDD.
        Fatal error: Call to a member function rowCount() on array in......
        

        $lastsave   = 0;
        $nbsave     = 0;
        $lastsql    = '';
        
        $requete = "SELECT UNIX_TIMESTAMP(save) AS lsave,fichier FROM cdc_saves ORDER BY save DESC;";
        $resultat = dbSelect($requete,$datas);
        $nbsave = $resultat->rowCount();
        	if($nbsave != 0) {
        		$donnees = $resultat->fetch();
        		$lastsave = $donnees->lsave;
        		$lastsql  = $donnees->fichier;
        	}
        
        0
        1. Modérateur
          A la place de rowcount.. fais juste in count($resultat);
          0
      4. merci encore une erreur avec fech. j'ai essayé fechAll et même fetchColumn
        Fatal error: Call to a member function fetchAll() on array in 
        
        0
        1. Modérateur
          A quelle ligne de code ???
          Si c'est après la fonction dbSelect.... Cest normal... Tu as déjà un array !
          0
      5. oui c'est après la fonction dbselec...
        $requete = "SELECT UNIX_TIMESTAMP(save) AS lsave,fichier FROM cdc_saves ORDER BY save DESC;";
        $resultat = dbSelect($requete,$datas);
        $nbsave = count($resultat);
        	if($nbsave != 0) {
        		$donnees = $resultat->fetch();
        		$lastsave = $donnees->lsave;
        		$lastsql  = $donnees->fichier;
        	}
        
        0
        1. Modérateur
          Fais donc un print_r($resultat); et regarde ce que ca donne... Tu devrais comprendre...
          0
      6. Cela me renvoie donc toutes mes sauvegardes sous forme d'objet?
        donc j'ai fait un foerach...
        $requete = "SELECT UNIX_TIMESTAMP(save) AS lsave,fichier FROM cdc_saves ORDER BY save DESC;";
        $resultat = dbSelect($requete,$datas);
        $nbsave = count($resultat);
        	if($nbsave != 0) {
        		foreach ($resultat as $donnees);
        		$lastsave = $donnees->lsave;
        		$lastsql  = $donnees->fichier;
        	}
        
        0
        1. Modérateur
          Et ben voila..
          0
        2. Les erreurs se suivent et ne se ressemble pas....
          J'ai une erreurs ou plutôt 4 notices (les mêmes à la même lignes) toujours dans le fichier init.php
          Que signifie cette erreur en fait j'essaie de regarder depuis un moment mais rien de bien précis.
          Merci
          Notice: Undefined offset: 2 in /home/cliquede/admin/libs/init.php on line 157
          
          0
      7. Bonjour,
        Quelque chose que je ne comprends pas c'est à propos des boucles while.
        Du coup j'ai cette erreur chaque fois que j'ai une boucle while. Je la remplace par foreach pourquoi??
        Merci
        while ($donnees = $resultat->fetch()) {
        
        Fatal error: Call to a member function fetch() on array in
        
        0
        1. Modérateur
          Pourquoi ? ... par ce que dans la fonction dbSelect ... tu as la ligne de code
          $result = $prep->fetchAll();
          

          Le résultat que tu obtiens de la fonction dbSelect ... est DEJA un (comme indiqué dans le message d'erreur.... )... ARRAY.
          Tu n'as donc pas besoin (et d'ailleurs, comme tu peux le voir, ça ne marche pas....) de faire un FETCH.... il est déjà fait !

          Si vraiement tu souhaites pouvoir faire tes fetch en dehors de la fonction.... dans ce cas il faut, soit modificer la fonction pour retirer la ligne .. soit en faire une nouvelle qui te permette de faire tes fetch en dehors.
          0
      8. J'ai compris merci.
        A propos de mon soucis initial pour mes requètes INSERT en fait j'ai uniquement 1 seule entrée qui est pris en compte c'est à dire si je coche plusieurs membres l'INSERT de l'idrep se fera qu'une fois.
        Voici l'exemple.
        table cdc_repetitions
        idrep drepet
        137 28/02/2018

        table cdc_assister
        idpers idrep idloc
        25 137 2
        38 0 2
        117 0 2
        if($_POST['submit']) {
        
        	$idrep		= $_POST['idrep'];
            $drepet     = dw2m($_POST['drepet']);
        	$idpers  	= $_POST['idpers'];
        	$idloc  	= $_POST['idloc'];
        
        	switch($_POST['haction']) {
        		case 'new':
            	$requete = "INSERT INTO cdc_repetitions (drepet) VALUES (:drepet)";
        	$datas = array('drepet'=>$drepet);
        	$idrep = dbInsert($requete,$datas);
        	$typenr = "enregistré";
        	$reqaj = $requete;
        			
        
        			$presents = isset($_POST['presents']) ? $_POST['presents'] : NULL;
        			
        		if (is_array($presents)) {	
        		    foreach($presents as $idpers) {
        			
        			$requete = "INSERT INTO cdc_assister (idpers,idrep,idloc) VALUES (:idpers,:idrep,:idloc)";
        	$datas = array('idpers'=>$idpers, 'idrep'=>$idrep, 'idloc'=>$idloc);
        	$idrep = dbInsert($requete,$datas);
        	$typenr = "enregistré";
        	$reqaj = $requete; 
        		    }
        		}
        			$success = "<span class='success'>Les présences à la répétition - ".trim(stripslashes(" du " . dateFR("$drepet")))." - a été $typenr.</span>";
        			break;
        	}
        }
        
        0
        1. Modérateur
          Je ne comprend pas trop ton explication......

          A propos de mon soucis initial pour mes requètes INSERT en fait j'ai uniquement 1 seule entrée qui est pris en compte c'est à dire si je coche plusieurs membres l'INSERT de l'idrep se fera qu'une foi

          ce que tu décris... c'est le comportement VOULU ... ou celui que tu constates actuellement ??

          Peux tu faire (en début de ton code )
          echo "<pre>";
          print_r($_POST);
          echo "</pre>";
          


          une fois avec un seul user
          une fois avec plusieurs

          et tu nous colles ça entre balises de code sur la discussion....
          0
      9. En fait l'INSERT de l'idrep est vide dans la table cdc_repetitions il y a bien l'enregistrement
        Array
        (
            [drepet] => 28/02/2018
            [idloc] => 2
            [haction] => new
            [idrep] => 
            [presents] => Array
                (
                    [0] => 110
                    [1] => 117
                )
        
            [submit] => Enregistrer
        )
        
        0
        1. Excuse moi j'ai résolu ce soucis.
          0
          1. Modérateur
            Donc... si le problème est réglé ... merci de mettre le sujet en RESOLU (via l'icone de roue cranté en haut de la discussion )
            0