[RESOLU] problème requête INSERT

Eléphanteau du PHP | 13 Messages

12 mai 2014, 11:25

Bonjour à tous,
j'ai un problème pour insérer une requête préparée dans les deux tables ci-dessous.
CREATE TABLE IF NOT EXISTS `commande` (
  `num_bon_commande` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `client` int(10) unsigned NOT NULL,
  `date_commande` date NOT NULL,
  `frait_port` decimal(4,2) NOT NULL DEFAULT '6.90',
  `montant_ttc` decimal(8,2) NOT NULL,
  `date_reglement` date NOT NULL,
  `moyen_paiement` varchar(20) NOT NULL,
  `paiement_valide` char(3) NOT NULL,
  `etat_cde` varchar(8) DEFAULT NULL,
  `statut_cde` varchar(12) DEFAULT NULL,
  PRIMARY KEY (`num_bon_commande`),
  KEY `fk_client_id` (`client`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=22

CREATE TABLE IF NOT EXISTS `contient` (
  `num_cde` int(10) unsigned NOT NULL,
  `id_prod` int(10) unsigned NOT NULL,
  `qte_choisi` int(3) unsigned NOT NULL,
  PRIMARY KEY (`num_cde`,`id_prod`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
"contient" est une table qui est aussi liée à une autre table "produit" non représentée.
je signale que la clé primaire de client n'est pas en auto increment c'est la requête d'insertion qui s'en charge.
je voudrais insérer des articles dans la table "commande" et "contient" après que le client ait renseigné ses coordonnées sur un formulaire.
deux cas: soit le client est authentifié dans ce cas le formulaire est déjà rempli et il n'a plus qu'a vérifier et à valider. ça, ça fonctionne
l'autre, il n'est pas authentifié et il doit s'inscrire puis entrer ses coordonnées manuellement s'il na pas envie de se connecter.

voilà une partie de la requête qui ne fonctionne pas:
j'ai fait un retour errorInfo() à certains endroits dont un (le deuxième est sur une autre requête qui à le même problème pour la table contient mais je ne l'ai pas mise) qui indique les erreurs en commentaires.
le problème est que mes requêtes fonctionnent bien sous phpMyadmin en mode sql avec des valeurs mais pas dans le script. visiblement d'après ce que dit errorInfo() client ne peut pas être nul ce qui prouverai que le SELECT après le INSERT n'est pas reconnu. j'ai regardé s'il n'y avait pas d'erreurs de syntaxe. Mais je ne vois pas où.
qu'en pensez vous ?
Merci pour votre aide .
<?php
//si le formulaire est rempli et que le client existe en bdd mais n'est pas connecté
if(!empty($_POST) AND !isset($_SESSION['id_compte']))
 $nom = $_POST['nom']; 
 $prenom= $_POST['prenom'];
 $adresse = $_POST['adresse'];
 $codePost = $_POST['code_postal'];
 $ville = $_POST['ville'];
 $pays= $_POST['pays'];
 $mail= $_POST['mail'];
 $tel = $_POST['telephone'];

	
	//on regarde si le client existe déjà , les champs telephone et e_ mail peuvent être vide ou pas
	$verifId = $bdd->prepare('SELECT COUNT(id_client) AS id FROM client
	WHERE nom = :nom AND prenom = :prenom AND adresse = :adresse AND code_postal = :codePost
	AND ville = :ville AND(telephone IS NULL OR telephone IS NOT NULL AND(e_mail IS NULL OR e_mail IS NOT NULL))') or die (print_r($bdd->errorInfo()));				
	$verifId->execute(array(
	'nom' => $nom,
	'prenom' => $prenom,
	'adresse' => $adresse,
	'codePost' => $codePost,
	'ville' => $ville));
	echo var_dump($verifId->errorInfo());		//pas d'erreur 
	
	//on vérifie si une ligne d'enregistrement existe
	$nbligne = $verifId->rowCount();
	$verifId->closeCursor();

	 //si le client existe on enregistre la commande
	 if($nbligne == 1)
	{
		 //requête d'insertion de la commande
		 $req1 = $bdd->prepare('INSERT INTO commande (client, date_commande, montant_ttc, date_reglement, moyen_paiement)VALUES((SELECT id_client AS numclient FROM client WHERE nom = :nom AND prenom = :prenom AND adresse = :adresse AND code_postal = :codePost AND ville = :ville AND pays = :pays AND (telephone IS NULL OR telephone IS NOT NULL AND (e_mail IS NULL OR e_mail IS NOTNULL))),  CURDATE(), :montantTTC, CURDATE(), :paiement)') or die (print_r($bdd->errorInfo()));
		$req1->execute(array(
		'nom'=> $nom,
		'prenom'=> $prenom,
		'adresse' => $adresse,
		'codePost' => $codePost,
		'ville' => $ville,
		'pays' =>  $pays,
		'montantTTC' => $_SESSION['cde_plus_frais'],
		'paiement' => $_SESSION['paiement']));
		echo var_dump($req1->errorInfo());				//erreur 'Column 'client' cannot be null'
		
			|
			|
			|
			|//reste du script
	}
?>

ViPHP
xTG
ViPHP | 7331 Messages

12 mai 2014, 13:01

CREATE TABLE IF NOT EXISTS `commande` (
`num_bon_commande` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`client` int(10) UNSIGNED NOT NULL
C'est pourtant assez clair.
Il est impossible d'insérer une commande sans renseigner ce champ d'après ton create table.
Ta base de donnée ne peut pas faire le lien toute seule entre ces deux tables.
Il faut donc de ton select précédent récupérer la clé primaire et l'ajouter dans la colonne client de ta requête insert.

Les clés étrangères sont principalement des contraintes d'intégrités, elles permettent de ne pas supprimer des enregistrements liés.
Pas de faire les liens toutes seules. ;)

Eléphanteau du PHP | 13 Messages

12 mai 2014, 13:42

ok merci pour ta réponse xtg, mais mais là mes tables sont déjà créées c'était juste pour monter leur structures.
ce que je ne comprend pas c'est pourquoi ça fonctionne sous php my admin et pas dans mon script.
en fait dans mon insert la sous requête SELECT est censée récupérer l'id_client puisque je vérifie les coordonnées correspondante dans la tables client . c'est bien possible une telle requête non ?.
quand je tape ma requête dans mysql avec des vraies valeurs et non des variable bien entendu
INSERT INTO commande (client, date_commande, montant_ttc, date_reglement, moyen_paiement)VALUES((SELECT id_client AS numclient FROM client WHERE nom = :nom AND prenom = :prenom AND adresse = :adresse AND code_postal = :codePost AND ville = :ville AND pays = :pays AND (telephone IS NULL OR telephone IS NOT NULL AND (e_mail IS NULL OR e_mail IS NOTNULL))),  CURDATE(), :montantTTC, CURDATE(), :paiement)
.

j'ai bien ma commande qui s'inscrit dans ma table . ou bien est ce problème dans mon tableau d'insertion ?

ViPHP
xTG
ViPHP | 7331 Messages

12 mai 2014, 14:48

Oooh... J'avais pas vu ce bout de requête...
Tu veux ma réponse ? Même si c'est possible c'est une horreur sans nom !
Pourquoi ne pas récupérer l'id dans ta requête précédente ?
Faire deux requêtes pour la même chose est pas top en plus de complexifier une requête existante.

Eléphanteau du PHP | 13 Messages

12 mai 2014, 14:57

ok merci xtg , ça à le mérite d'être clair :)
c'est peut être pour ça que ça ne fonctionne pas (trop tordu comme solution)
je vais me pencher sur le problème et tenter ta solution .

Eléphanteau du PHP | 13 Messages

13 mai 2014, 09:48

Bonjour
suite à mon post d'hier je le remet sur le grill !
j'ai modifier mon de façon à récupérer mon identifiant à partir de ma première requête . donc pour ça , c'est bon.
après je modifie la seconde pour y injecter mon id avec ma requête préparée el là paff un beau Array to string conversion
que m'indique php au niveau de mon tableau d'insertion. pourtant je ne vois pas où ça cloche mes variables sont bien des chaines quand je fait un var_dump() ; et j'ai fait la même requête quasiment identique un peu plus bas dans une autre condition et ça fonctionne .si vous pouviez m'expliquer parce que là ....
merci d'avance
//on regarde si le client existe déjà 
	$verifId = $bdd->prepare('SELECT id_client AS id FROM client
	WHERE nom = :nom AND prenom = :prenom AND adresse = :adresse AND code_postal = :codePost
	AND ville = :ville AND pays = :pays AND(telephone IS NULL OR telephone = :tel AND(e_mail IS NULL OR e_mail = :mail))')
	or die (print_r($bdd->errorInfo()));				
	$verifId->execute(array(
	'nom' => $nom,
	'prenom' => $prenom,
	'adresse' => $adresse,
	'codePost' => $codePost,
	'ville' => $ville,
	'pays' => $pays,
	'tel' => $tel,
	'mail' => $mail));
	$idClient = $verifId->fetch();
	$verifId->closeCursor();
	
	 //si l'identifiant du client existe on enregistre la commande
	 if($idClient != 0)
	{	
		 //requête d'insertion de la commande
		 $req = $bdd->prepare('INSERT INTO commande (client, date_commande, montant_ttc, date_reglement, moyen_paiement)
		VALUES (:client, CURDATE(), :total, CURDATE(), :paiement)') or die (print_r($bdd->errorInfo()));
		$req->execute(array(
		'client' => $idClient,
		'total' => $_SESSION['cde_plus_frais'],
		'paiement' => $_SESSION['paiement']   // Array to string conversion
		));

ViPHP
xTG
ViPHP | 7331 Messages

13 mai 2014, 11:17

PDO::fetch() te renvoie un array.
Si tu fais un var_dump de $idClient tu devrais voir un truc du genre :
Array(1) => ( [id] => ... )
Et donc tu dois l'utiliser comme ceci :
$idClient['id']

Eléphanteau du PHP | 13 Messages

13 mai 2014, 18:42

Merci beaucoup xTG , grâce à toi ça fonctionne ! :D