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 :

Insert de plusieurs entrée avec Classe CRUD


Sujet :

PHP & Base de données

  1. #1
    Membre habitué
    Inscrit en
    Août 2010
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 12
    Par défaut Insert de plusieurs entrée avec Classe CRUD
    Bonjour,

    J'utilise cette classe CRUD et j'aimerai faire une requête insert de plusieurs entrées.

    Voici ce que j'obtient lorsque j'affiche le tableau $values passé en paramètre :

    Array
    (
    [0] => Array
    (
    [nom] => dupont
    [prenom] => julien
    [societe] => fichier
    [email] => julien.dupont@hotmail.com
    )

    [1] => Array
    (
    [nom] => Durant
    [prenom] => lkuh
    [societe] => fichier
    [email] => durant@gmail.com
    )

    )
    Et voici l'erreur :

    Exception levée dans l'application.
    Message SQLSTATE[HY093]: Invalid parameter number: parameter was not defined
    Si quelqu'un comprend comment envoyer plusieurs entrées en une requête...

    Merci d'avance.

  2. #2
    Modérateur

    Avatar de MaitrePylos
    Homme Profil pro
    DBA
    Inscrit en
    Juin 2005
    Messages
    5 505
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : DBA
    Secteur : Service public

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 505
    Par défaut
    peux-t-on voir ton code, ainsi que la définition de ta table ?

  3. #3
    Expert confirmé
    Avatar de Benjamin Delespierre
    Profil pro
    Développeur Web
    Inscrit en
    Février 2010
    Messages
    3 929
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2010
    Messages : 3 929
    Par défaut
    Message SQLSTATE[HY093]: Invalid parameter number: parameter was not defined
    C'est probablement un problème dû au requêtes préparées. Il doit de manquer des valeurs dans le tableau de remplacement, regarde par ici: http://www.php.net/manual/en/pdostatement.execute.php

    Vérifie et reviens nous voir

  4. #4
    Membre habitué
    Inscrit en
    Août 2010
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 12
    Par défaut
    Voici mon code :

    Controller :

    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
     
    $this->add($contact->Contact);
     
       public function add($tab = null) {
            if(is_null($tab)){
     
    			}else{
    				$tab = array_values($tab);
    				if(count($tab) > 1){  //Si j'ai plus de une entré à envoyer
    					$values = array();
     
                        foreach($tab as $key=>$value){
                        	array_push($values, array('nom'=>$tab[$key]->nom,'prenom'=>$tab[$key]->prenom,'societe'=>$tab[$key]->societe,'email'=>$tab[$key]->email));
                        }
     
    					$this->data->AddEmail($values);
    				}else{    // Si je n'ai qu'une entré à envoyer ça marche...
                        $values = array('nom'=>$tab[0]->nom,'prenom'=>$tab[0]->prenom,'societe'=>$tab[0]->societe,'email'=>$tab[0]->email);
     
    					$this->data->AddEmail($values);
                    }
     
    			}
     
     
        }
    Model :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    public function AddEmail($values){
    		$this->dbInsert('emails', $values);
    		return $r;	
    	}
    Classe CRUD :

    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
     
     public function dbInsert($table, $values)
            {
                /*** snarg the field names from the first array member ***/
                $fieldnames = array_keys($values);
                /*** now build the query ***/
                $size = sizeof($fieldnames);
                $i = 1;
                $sql = "INSERT INTO $table";
                /*** set the field names ***/
                $fields = '( ' . implode(' ,', $fieldnames) . ' )';
                /*** set the placeholders ***/
                $bound = '(:' . implode(', :', $fieldnames) . ' )';
                /*** put the query together ***/
                $sql .= $fields.' VALUES '.$bound;
                /*** prepare and execute ***/
    			$stmt = BDinstance::getInstance()->prepare($sql);
     
    			/* echo '<pre>';
                 print_r($sql);
                 echo '</pre>';
    			*/
    			return $stmt->execute($values);
            }
    et voici ma table :

    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
     
    CREATE TABLE `emails` (
      `id` int(11) NOT NULL auto_increment,
      `email` varchar(255) NOT NULL,
      `nom` varchar(255) NOT NULL,
      `societe` varchar(255) NOT NULL,
      `prenom` varchar(255) NOT NULL,
      `adresse` text NOT NULL,
      `cp` char(5) NOT NULL,
      `ville` varchar(255) NOT NULL,
      `tel` char(10) NOT NULL,
      `url` tinytext NOT NULL,
      `commentaire` text NOT NULL,
      `date_inscri` date NOT NULL,
      `valid` tinyint(1) NOT NULL,
      PRIMARY KEY  (`id`),
      UNIQUE KEY `email` (`email`)
    ) ENGINE=MyISAM AUTO_INCREMENT=24 DEFAULT CHARSET=latin1 AUTO_INCREMENT=24 ;

  5. #5
    Membre Expert Avatar de Madfrix
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    2 326
    Détails du profil
    Informations personnelles :
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 326
    Par défaut
    Bonjour,

    tu mets à jour ta table emails avec 4 colonnes (nom, prenom, société, email) mais cette table contient d'autres colonnes qui ne peuvent pas être nulles (en fait toutes tes colonnes). Vu qu'elles n'ont pas de valeurs par défaut, tu as une erreur d'insertion

  6. #6
    Membre habitué
    Inscrit en
    Août 2010
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 12
    Par défaut
    Bonjour et merci pour ta réponse,

    Je me suis posé la question en écrivant le message. Je test ce soir et je vous redis demain.

    Encore merci et bonne journée

  7. #7
    Membre habitué
    Inscrit en
    Août 2010
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 12
    Par défaut
    J'ai changer quelques petites choses :

    Controller :

    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
     
    public function add($tab = null) {
            if(is_null($tab)){
     
    			}else{
    				$tab = array_values($tab);
    				if(count($tab) > 1){  //Si j'ai plus de une entré à envoyer
    					$values = array();
     
                    /*    foreach($tab as $key=>$value){
                        	array_push($values, array('nom'=>$tab[$key]->nom,'prenom'=>$tab[$key]->prenom,'societe'=>$tab[$key]->societe,'email'=>$tab[$key]->email));
                        }
                      */
     
    				   array_push($values, array('nom'=>'nom1','prenom'=>'prenom1','societe'=>'societe1','email'=>'email1@test.fr'));
                       array_push($values, array('nom'=>'nom2','prenom'=>'prenom2','societe'=>'societe2','email'=>'email2@test.fr'));
     
                       $this->data->AddEmail($values);
    				}else{    // Si je n'ai qu'une entré à envoyer ça marche...
                        $values = array('nom'=>$tab[0]->nom,'prenom'=>$tab[0]->prenom,'societe'=>$tab[0]->societe,'email'=>$tab[0]->email);
     
    					$this->data->AddEmail($values);
                    }
     
    			}
     
     
        }
    La structure de la table :

    CREATE TABLE `emails` (
    `id` int(11) NOT NULL auto_increment,
    `email` varchar(255) NOT NULL,
    `nom` varchar(255) NOT NULL,
    `societe` varchar(255) NOT NULL,
    `prenom` varchar(255) NOT NULL,
    `adresse` text,
    `cp` char(5) default NULL,
    `ville` varchar(255) default NULL,
    `tel` char(10) default NULL,
    `url` tinytext,
    `commentaire` text,
    `date_inscri` date default NULL,
    `valid` tinyint(1) default NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY `email` (`email`)
    ) ENGINE=MyISAM AUTO_INCREMENT=24 DEFAULT CHARSET=latin1 AUTO_INCREMENT=24 ;
    Et j'ai toujours la même erreur, et lorsque je fais le test avec ce tableau :
    Array
    (
    [nom] => dupont
    [prenom] => julien
    [societe] => fichier
    [email] => julien.dupont@hotmail.com
    )
    Cela fonctionne alors qu'avec ce tableau :

    Array
    (
    [0] => Array
    (
    [nom] => dupont
    [prenom] => julien
    [societe] => fichier
    [email] => julien.dupont@hotmail.com
    )

    [1] => Array
    (
    [nom] => Durant
    [prenom] => lkuh
    [societe] => fichier
    [email] => durant@gmail.com
    )

    )
    Cela de fonctionne pas.

  8. #8
    Membre Expert Avatar de Madfrix
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    2 326
    Détails du profil
    Informations personnelles :
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 326
    Par défaut
    Essaies de modifier comme ceci :

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    public function AddEmail($values){
        foreach($values as $value)
            $this->dbInsert('emails', $value);
    }

  9. #9
    Membre habitué
    Inscrit en
    Août 2010
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 12
    Par défaut
    Bonjour,

    Le problème avec cette méthode c'est que je fais une requête pour chaque email a insérer dans la table et la but de mon application est de faire de l'import à partir d'un fichier .csv qui peux être très volumineux (3000 entrées par exemple donc 3000 requêtes). Je pense que comme ça, ça sera pas optimisé.
    Il doit forcément y avoir un moyen de tous envoyer en une requête.
    Merci quand même.

  10. #10
    Membre Expert Avatar de Madfrix
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    2 326
    Détails du profil
    Informations personnelles :
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 326
    Par défaut
    teste cela je pense que ca devrait être bon :

    Code php : 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
     
    public function dbInsert($table, $values) {
     
    	$bound = '';
    	$bindParams = array();
    	$fieldnames = array_keys($values[0]);
     
        $sql = 'INSERT INTO '. $table;
     
        $fields = '( ' . implode(', ', $fieldnames) . ' )';
     
    	foreach($values as $key=>$value) {
    		$bound .= ' (';
    		foreach($fieldnames as $fieldname) {
    			$param = ':' . $fieldname.$key . ', ';
    			$bound .= $param;
    			$bindParams[] = array('param'=>$param, 'value'=>$value[$fieldname]);
    		}
    		$bound = substr($bound, 0, -2);
    		$bound .= '), ';
    	}
     
    	$bound = substr($bound, 0, -2);
     
        $sql .= $fields.' VALUES '.$bound;	
     
    	$stmt = BDinstance::getInstance()->prepare($sql);
     
    	foreach($bindParams as $value)
    		$stmt->bindParam($value['param'], $value['value']);
     
    	return $stmt->execute($values);
    }

  11. #11
    Modérateur

    Avatar de MaitrePylos
    Homme Profil pro
    DBA
    Inscrit en
    Juin 2005
    Messages
    5 505
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : DBA
    Secteur : Service public

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 505
    Par défaut
    C'est choux blancs et blancs choux, de plus imagine qu'il ne passe pas le même nombres de paramètres dans ses tableaux

    le code suivants, va lui poser soucis
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    $fieldnames = array_keys($values[0]);
    Et cela lui fera quand même 3000 requêtes.

  12. #12
    Membre Expert Avatar de Madfrix
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    2 326
    Détails du profil
    Informations personnelles :
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 326
    Par défaut
    Citation Envoyé par MaitrePylos Voir le message
    de plus imagine qu'il ne passe pas le même nombres de paramètres dans ses tableaux
    Là je suis d'accord, libre à lui de modifier un peu le code pour adapter à ses besoins

    Citation Envoyé par MaitrePylos Voir le message
    Et cela lui fera quand même 3000 requêtes
    Là je suis pas d'accord, cela lui fera une seule requête de ce type :

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    INSERT INTO saTable (C1, C2)
    VALUES (val1, val2),
    (val3, val4),
    (val5, val6)

    EDIT: de toute manière s'il ne passe pas le même nombres de paramètres dans ses tableaux, il sera oblié de faire des requêtes d'insertions unitaires donc de passer par la méthode que je lui ai proposé dans le post #8

  13. #13
    Membre habitué
    Inscrit en
    Août 2010
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 12
    Par défaut
    Bonjour et merci pour l'intérêt que vous portez sur mon problème.

    Ma requête semble être correcte :

    INSERT INTO emails( nom, prenom, societe, email ) VALUES (:nom0, :prenom0, :societe0, :email0), (:nom1, :prenom1, :societe1, :email1)
    Mais j'ai toujour la même erreur :

    Exception levée dans l'application.
    Message SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens
    Fichier /homepages/0/d341517557/htdocs/mailer/application/core/crud.phpLigne 145
    voici mon tableau de test :

    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
    Array
    (
        [0] => Array
            (
                [nom] => nom1
                [prenom] => prenom1
                [societe] => societe1
                [email] => email1@test.fr
            )
     
        [1] => Array
            (
                [nom] => nom2
                [prenom] => prenom2
                [societe] => societe2
                [email] => email2@test.fr
            )
     
    )

  14. #14
    Membre Expert Avatar de Madfrix
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    2 326
    Détails du profil
    Informations personnelles :
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 326
    Par défaut
    Bonjour,

    écris cela juste avant le dernier foreach de ta fonction et controle si tu as autant de paramètres que de valeurs avec la requête SQL (j'ai pas testé le code que je t'ai proposé) :

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    echo '<pre>';
    print_r($bindParams);
    echo '</pre>';

  15. #15
    Membre habitué
    Inscrit en
    Août 2010
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 12
    Par défaut
    Voici le résultat de mon echo :

    Array
    (
    [0] => Array
    (
    [param] => :nom0,
    [value] => nom1
    )

    [1] => Array
    (
    [param] => :prenom0,
    [value] => prenom1
    )

    [2] => Array
    (
    [param] => :societe0,
    [value] => societe1
    )

    [3] => Array
    (
    [param] => :email0,
    [value] => email1@test.fr
    )

    [4] => Array
    (
    [param] => :nom1,
    [value] => nom2
    )

    [5] => Array
    (
    [param] => :prenom1,
    [value] => prenom2
    )

    [6] => Array
    (
    [param] => :societe1,
    [value] => societe2
    )

    [7] => Array
    (
    [param] => :email1,
    [value] => email2@test.fr
    )

    )

  16. #16
    Membre Expert Avatar de Madfrix
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    2 326
    Détails du profil
    Informations personnelles :
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 326
    Par défaut
    Désolé, j'ai pas corrigé le execute dans la fonction. Mets ceci à la place pour voir :

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    return $stmt->execute();

  17. #17
    Membre habitué
    Inscrit en
    Août 2010
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 12
    Par défaut
    Bonjour,

    Finalement cela fonctionne avec la fonction de Madfrix un tout petit peu modifiée :

    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
     
    public function dbMultiInsert($table, $values) {
    		    $bound = '';
    		    $bindParams = array();
    		    $fieldnames = array_keys($values[0]);   
    		    $sql = 'INSERT INTO '. $table;
     
    		    $fields = '( ' . implode(', ', $fieldnames) . ' )';
     
    		    foreach($values as $key=>$value) {
    		        $bound .= ' (';
    		        foreach($fieldnames as $fieldname) {
    					$param = '"' . $value[$fieldname] . '", ';
    		            $bound .= $param;
    		            $bindParams[] = array('param'=>$param, 'value'=>$value[$fieldname]);
    		        }
    		        $bound = substr($bound, 0, -2);
    		        $bound .= '), ';
    		    }		        
    		    $bound = substr($bound, 0, -2);
    		    $sql .= $fields.' VALUES '.$bound;  
    		    $stmt = BDinstance::getInstance()->prepare($sql);
    			foreach($bindParams as $value)
    		        $stmt->bindParam($value['param'], $value['value']);
     
    			return $stmt->execute();
    		}

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

Discussions similaires

  1. [MySQL] Formulaire multiples et INSERT sur plusieures tables avec même ID
    Par mfredok dans le forum PHP & Base de données
    Réponses: 13
    Dernier message: 25/11/2010, 13h59
  2. [MySQL] erreur à l'insert d'une entrée avec un champ ENUM
    Par mounia.n dans le forum PHP & Base de données
    Réponses: 4
    Dernier message: 27/05/2008, 16h44
  3. Insertion dans plusieurs table avec un index commun
    Par irongomme dans le forum Requêtes
    Réponses: 3
    Dernier message: 12/10/2007, 11h41
  4. Réponses: 5
    Dernier message: 07/06/2007, 17h47
  5. plusieurs instance de classe avec thread
    Par lucky dans le forum MFC
    Réponses: 2
    Dernier message: 14/09/2006, 11h30

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