Problèmes jointures PHP et SQL

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : Problèmes jointures PHP et SQL

Re: Problèmes jointures PHP et SQL

par yann18 » 20 mars 2014, 12:40

Finalement c'est bon, je viens de trouver l'erreur, la fonction doit plutôt ressembler à ça :
	public function query($sql, $data = null) {
		if($data !== null) {
			$requete = $this->db->prepare($sql);
			$requete->execute($data);
		}
		else {
			$requete = $this->db->query($sql);
		}
		return $requete->fetchAll(PDO::FETCH_OBJ);
	}
Merci encore pour toute votre aide :)
sur ce coup t'as bien très bien fait d'utiliser le else.

Re: Problèmes jointures PHP et SQL

par nicosjack » 19 mars 2014, 11:07

Finalement c'est bon, je viens de trouver l'erreur, la fonction doit plutôt ressembler à ça :
	public function query($sql, $data = null) {
		if($data !== null) {
			$requete = $this->db->prepare($sql);
			$requete->execute($data);
		}
		else {
			$requete = $this->db->query($sql);
		}
		return $requete->fetchAll(PDO::FETCH_OBJ);
	}
Merci encore pour toute votre aide :)

Re: Problèmes jointures PHP et SQL

par nicosjack » 19 mars 2014, 10:58

Merci beaucoup !

Par contre malheureusement pour mes requêtes préparées, j'obtiens une erreur de syntaxe SQL : 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 '?'

Voici un exemple de requête préparée qui ne fonctionne plus :
$produits = $DB->query('SELECT * FROM produits WHERE date_livraison = ?', array($datelivraison));

Re: Problèmes jointures PHP et SQL

par yann18 » 18 mars 2014, 18:57

Il faut réécrire la méthode query de la classe DB de telle sorte qu'elle exécute soit une requête sql préparée soit une requête sql non preparée.
//DB.php
//classe DB
 //exécute une requête préparée si le paramètre $data est present sinon exécute une requête non preparée
        public function query($sql, $data = null ) {
	  $requete = $this->db->query( $sql );
	  if(  $data !==null ) {
               $requete = $this->db->prepare( $sql );
               $requete->execute($data);
	  }
        return $requete->fetchAll(PDO::FETCH_OBJ);
        }
Quand je fais une requête et que j'essaye de compter combien de lignes sont retournées, j'obtiens une erreur également
pour compter le nombre de lignes :
$requete = $DB->query('SELECT count(*) as nombreDeClients FROM clients');
var_dump($requete);

Re: Problèmes jointures PHP et SQL

par nicosjack » 16 mars 2014, 14:28

Énorme merci à toi !! Tout fonctionne parfaitement, c'est super :D

J'ai juste une dernière petite question qui m'aidera probablement pour la suite :
Quand je fais une requête et que j'essaye de compter combien de lignes sont retournées, j'obtiens une erreur également :
$requete = $DB->query('SELECT nom_client FROM clients');
$requete->rowCount();
Voici l'erreur :
Call to a member function rowCount() on a non-object

Pourquoi j'ai toujours cette erreur ?

Re: Problèmes jointures PHP et SQL

par yann18 » 14 mars 2014, 19:17

Fatal error: Call to undefined method PDOStatement::lastInsertId() in C:\wamp\www\commande\panier.php on line 31
il y a une coquille qui s'est glissée. en effet lastInsertId() appartient à PDO et non à PDOStatement.Pour récupérer le dernier id inséré on va modifier la méthode insert de la classe DB de telle sorte qu'elle renvoie l'id qui vient d'être inséré.

Pour l'insertion multiple dans la table detailscommande, on va ajouter une méthode dans DB qui permet juste de préparer une requête pour pouvoir par la suite boucler que sur le tableau des paramètres de la requête pour l'exécuter.
<?php

class DB {
       
        private $host = 'localhost';
        private $username = 'root';
        private $password = '';
        private $database = 'schwoob';
        private $db;
        
       
        public function __construct($host = null, $username = null, $password = null, $database = null) {
                if($host != null) {
                        $this->host = $host;
                        $this->username = $username;
                        $this->password = $password;
                        $this->database = $database;
                }
               
                //Connexion à la BDD
                try {
                        $this->db = new PDO('mysql:host='.$this->host.';dbname='.$this->database, $this->username, $this->password, array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES UTF8', PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING));
                } catch(PDOException $e) {
                        die('<h1>Impossible de se connecter à la base de données</h1>');
                }
        }
       
        //Fonction query permettant d'executer facilement des requêtes préparées en fonction de paramètres
        public function query($sql, $data = array()) {
                $requete = $this->db->prepare($sql);
                $requete->execute($data);
                return $requete->fetchAll(PDO::FETCH_OBJ);
        }

	/*
	@return 0 or primary key
	*/
        public function insert($sql, $data = array()) {
                $requete = $this->db->prepare($sql);
                $reponse = $requete->execute($data);
                return (empty($reponse) ) ? 0 : $this->db->lastInsertId(); 
        }

	 public function insertMultiple( $sql){
	 $requete = $this->db->prepare($sql);
	return $requete;
	}

	

	
}


et dans le panier.php

//require_once 'DB.php';
//$DB = new DB();


  //On ajoute la commande dans la table commandes
 $requete = $DB->insert('INSERT INTO commandes (date_commande, date_livraison, clients_id_clients) 
			VALUES(NOW(), :date_livraison, :id_client)', 
			array(
                                ':date_livraison' => $date_livraison,
                                ':id_client' => $_SESSION['id'])
			     );
//la méthode $DB->insert() renvoie le dernier id de la commande inserée 
// sinon elle renvoie 0 en cas d'échec d'insertion dans la table commande
if(  $requete  !==0 )     //l'id de la commande inserée est-il different de 0?                                    
 //recuperation de l'id de la commande insérée
 $commande_id = $requete;
else
echo "Impossible d'inserer dans la table commande";


 //Insertion dans la table detailscommande
$prepare = $DB->insertMultiple("INSERT INTO detailscommande VALUES (:commande_id, :produit_id, :quantite )" );
foreach($_SESSION['panier'] as $produit_id=> $quantite ){
 $prepare->execute(array(
         ':commande_id' => $commande_id,
        ':produit_id' =>  $produit_id,
        ':quantite' => $quantite,
        ));

}//foreach

Re: Problèmes jointures PHP et SQL

par nicosjack » 14 mars 2014, 17:05

Merci beaucoup j'ai bien avancé grâce à ta réponse :D

Par contre j'ai encore un problème, j'obtiens l'erreur suivante :
Fatal error: Call to undefined method PDOStatement::lastInsertId() in C:\wamp\www\commande\panier.php on line 31
Voici la ligne 31 : $commande_id = $requete->lastInsertId();
Et voici le code complet :
				//On ajoute la commande dans la table commandes
				$requete = $DB->insert('INSERT INTO commandes (date_commande, date_livraison, clients_id_clients) VALUES(NOW(), :date_livraison, :id_client)', array(
				'date_livraison' => $date_livraison,
				'id_client' => $_SESSION['id']));
				
			
				//recuperation de l'id de la commande insérée
				$commande_id = $requete->lastInsertId();
Voici également le contenu de ma classe DB :
class DB {
	
	private	$host = 'localhost';
	private $username = 'root';
	private $password = '';
	private $database = 'schwoob';
	private $db;
	
	public function __construct($host = null, $username = null, $password = null, $database = null) {
		if($host != null) {
			$this->host = $host;
			$this->username = $username;
			$this->password = $password;
			$this->database = $database;
		}
		
		//Connexion à la BDD
		try {
			$this->db = new PDO('mysql:host='.$this->host.';dbname='.$this->database, $this->username, $this->password, array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES UTF8', PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING));
		} catch(PDOException $e) {
			die('<h1>Impossible de se connecter à la base de données</h1>');
		}
	}
	
	//Fonction query permettant d'executer facilement des requêtes préparées en fonction de paramètres
	public function query($sql, $data = array()) {
		$requete = $this->db->prepare($sql);
		$requete->execute($data);
		return $requete->fetchAll(PDO::FETCH_OBJ);
	}
	public function insert($sql, $data = array()) {
		$requete = $this->db->prepare($sql);
		$requete->execute($data);
		return $requete;
	}
}

Re: Problèmes jointures PHP et SQL

par yann18 » 13 mars 2014, 16:37

dans ta table commandedetails les champs commande_id_commande et produit_id_produit ne doivent pas être des clés primaires.cette table peut être dépourvue de clé primaire.
try {  

$base = new PDO( 'mysql:host=localhost;dbname=bbd;charset=utf8', 'user', 'password');
  $base->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

// Démarre explicitement une transaction
  $base->beginTransaction();

 //On ajoute la commande dans la table commandes
$requete = $base->prepare('INSERT INTO commandes (date_commande, date_livraison, clients_id_clients) VALUES(NOW(), :date_livraison, :id_client)');
$requete->execute(array(
        'date_livraison' => $date_livraison,
        'id_client' => $_SESSION['id']
));

//recuperation de l'id de la commande insérée
$commande_id = $requete ->lastInsertId(); 

//Insertion dans la table detailscommande
$req2 = $base->prepare("INSERT INTO detailscommande VALUES (:commande_id, :produit_id, :quantite )");

foreach($_SESSION['panier'] as $produit_id=> $quantite ){
 $req2->execute(array(
         ':commande_id' => $commande_id,
        ':produit_id' =>  $produit_id,
	':quantite' => $quantite,
	));

}
  $base->commit();//on valide la transaction=> insertion dans la table commande et detailscommande

}catch (PDOException $e) {
   // Si l'une des requête a echouée alors
      //on  annule les changements de toutes les requêtes faisant partie
      // de la transaction, même celles qui se sont bien déroulées.
  $dbh->rollBack();
   printf("erreur sql liée  à l'insertion jour: %s:", $e->getMessage());
}


Re: Problèmes jointures PHP et SQL

par nicosjack » 13 mars 2014, 15:28

Merci beaucoup pour ton aide :)

Voilà ce que contient ma variable de SESSION en faisant un var_dump($_SESSION) :
array
  'panier' => 
    array
      8 => string '3' (length=1)
      12 => string '6' (length=1)
      15 => string '2' (length=1)
  'id' => string '1' (length=1)
  'societe' => string 'ma-societe' (length=14)
8, 12 et 15 correspondent aux ID des produits ajoutés au panier.
3, 6, 2 correspondent à leur quantité respective.
'id' correspond à l'ID du client qui passe commande et 'société' correspond à son nom (pour afficher un message de bienvenue sur l'accueil)

Donc si je comprend bien, je vais plusieurs requêtes simples pour insérer mes données dans les tables ? Donc je n'ai pas de INNER JOIN, LEFT JOIN etc à utiliser ?

Re: Problèmes jointures PHP et SQL

par damien_55 » 13 mars 2014, 13:01

Hello,

Il te suffit par exemple de créer une page de confirmation de commande (Votre commande a été prise en compte).

Cette page recupere les données posté par la page récapitulatif de la commande (les données en session) et cette page contient une requete d'insertion classique dans ta base. (mysql_query insert.....).

Je ne sais pas comment est faite ta base, et ce que tu recuperes exactement en sessions.

Pour avancer, creer cette page de validation, fait un echo de tes variables en sessions ( ce qui est validé par ton formulaire). à partir de cet echo, fait une requete classique d'insertion dans tes tables. Il se peut que tu ai plusieurs requetes puisque plusieurs tables.

Ne te préoccupe pas de la serialisation des données pour l'instant. (c'est un peu de l'optimisation et ça marche trés bien sans.)

Je reste dans le coin.

Re: Problèmes jointures PHP et SQL

par nicosjack » 13 mars 2014, 11:39

Plus personne pour me répondre ?

Re: Problèmes jointures PHP et SQL

par nicosjack » 11 mars 2014, 15:17

Merci pour ta réponse, voici le tuto que j'ai suivi et appliqué en entier : http://www.grafikart.fr/tutoriels/php/p ... ession-309

Et voici le code de mon fichier panier.php qui affiche le récapitulatif de la commande :
<section id="main">
		<a href="index.php" title="Retour à la page d'accueil">Retour</a>
		<?php 
			$ids = array_keys($_SESSION['panier']);
		
			//On récupère tous les produits ajoutés au panier
			if(empty($ids)) {
				$produits = array();
			} else {
				$produits = $DB->query('SELECT * FROM produits WHERE id_produit IN ('.implode(',', $ids).')');
			}
		?>
		<form method="post" action="panier.php">
			<table>
				<thead>
					<tr>
						<th>Nom</th>
						<th>Prix</th>
						<th>Quantité</th>
						<th>Sous-total</th>
						<th>Actions</th>
					</tr>
				</thead>
				<tbody>
					<?php foreach($produits as $produit): ?>
					<tr>
						<td><?php echo $produit->nom_produit; ?></td>
						<td><?php echo number_format($produit->prix_unitaire, 2, ',', ' '); ?> €</td>
						<td><input class="spinner" type="number" name="panier[quantite][<?php echo $produit->id_produit; ?>]" value="<?php echo $_SESSION['panier'][$produit->id_produit]; ?>" /></td>
						<td><?php echo number_format($produit->prix_unitaire * $_SESSION['panier'][$produit->id_produit], 2, ',', ' '); ?> €</td>
						<td><a href="panier.php?delpanier=<?php echo $produit->id_produit; ?>" title="Supprimer le produit">Supprimer</a></td>
					</tr>
					<?php endforeach; ?>
				</tbody>
			</table>
			<input type="submit" value="Recalculer" />
		</form>
		<strong>NOMBRE DE PRODUITS : <?php echo $panier->compter(); ?></strong>
		<strong>TOTAL : <?php echo number_format($panier->total(), 2, ',', ' '); ?> €</strong>
		<button>Valider la commande</button>
	</section>
Et voici le code du fichier panier.class.php qui est appelé dans le header de la page :
<?php

class panier {
	
	private $DB;
	
	//Constructeur
	public function __construct($DB) {
		
		//S'il n'existe aucune session, on l'a créer
		if(!isset($_SESSION)) {
			session_start();
		}
		
		//Si aucun panier n'existe, on le créer
		if(!isset($_SESSION['panier'])) {
			$_SESSION['panier'] = array();
		}
		$this->DB = $DB;
		
		if(isset($_GET['delpanier'])) {
			$this->del($_GET['delpanier']);
		}
		
		if(isset($_POST['panier']['quantite'])) {
			$this->recalc();	
		}
	}

	//Fonction permettant de recalculer le panier quand on change la quantité
	public function recalc() {
		foreach($_SESSION['panier'] as $product_id => $quantite) {
			if(isset($_POST['panier']['quantite'][$product_id])) {
				if(filter_var($_POST['panier']['quantite'][$product_id], FILTER_VALIDATE_INT) && $_POST['panier']['quantite'][$product_id] > 0) {
					$_SESSION['panier'][$product_id] = $_POST['panier']['quantite'][$product_id];
				}
				else {
					echo 'Attention, la quantité renseignée doit être un chiffre entier positif.';	
				}
			}
		}
	}
	
	//Fonction permettant de compter combien il y a de produits dans le panier
	public function compter() {
		return array_sum($_SESSION['panier']);
	}
	
	//Fonction permettant de calculer le prix total du panier
	public function total() {
		
		$total = 0;
		$ids = array_keys($_SESSION['panier']);
		
		//On récupère tous les produits ajoutés au panier
		if(empty($ids)) {
			$produits = array();
		} else {
			$produits = $this->DB->query('SELECT id_produit, prix_unitaire FROM produits WHERE id_produit IN ('.implode(',', $ids).')');
		}
		
		foreach($produits as $produit) {
			$total += $produit->prix_unitaire * $_SESSION['panier'][$produit->id_produit];	
		}
		return $total;
	}
	
	//Fonction permettant d'ajouter un produit au panier
	public function add($product_id) {
		
		//Si le panier contient déjà ce produit
		if(isset($_SESSION['panier'][$product_id])) {
			//On en ajoute un
			$_SESSION['panier'][$product_id]++;
		} else {
			//Sinon on en créer un
			$_SESSION['panier'][$product_id] = 1;	
		}
	}
	
	public function del($product_id) {
		unset($_SESSION['panier'][$product_id]);	
	}
}

?>

Re: Problèmes jointures PHP et SQL

par damien_55 » 11 mars 2014, 12:32

Slt,

Félicitations :wink: .

Quel tuto, tu as utilisé ? parce que sans le code, on va avoir du mal a te suivre. Donne le code de la page de confirmation de ton panier là ou arrive le recap de ta commande pour validation finale du client.

Re: Problèmes jointures PHP et SQL

par nicosjack » 11 mars 2014, 10:57

Merci encore, j'ai effectivement suivi un très bon tutoriel qui m'a permis de réaliser correctement un panier (avec les sessions) et tout fonctionne bien :)
Maintenant malheureusement, le tutoriel s'arrête juste avant d'insérer les données dans la base et donc je bloque toujours au même endroit... Le formateur explique brièvement que l'on peut utiliser la fonction serialize() de PHP mais j'ai toujours du mal à comprendre comment insérer les données et faire en sorte qu'elles soient liées... :?

Re: Problèmes jointures PHP et SQL

par yann18 » 09 mars 2014, 16:56

J'arrive à remplir ma table "commandes" en mettant l'id du client, la date de commande et la date de livraison, mais comment remplir la table "detailscommande" en y mettant l'id de la commande (qui vient donc d'être généré par la première requete), l'id du client, chaque produit et sa quantité respective... ?
On récupère le dernier id inséré avec la fonction lastInsertId() de PDO.

//On ajoute la commande dans la table commandes
$requete = $base->prepare('INSERT INTO commandes (date_commande, date_livraison, clients_id_clients) VALUES(NOW(), :date_livraison, :id_client)');
$requete->execute(array(
        'date_livraison' => $date_livraison,
        'id_client' => $_SESSION['id']
));

//id de la commande insérée
$requete ->lastInsertId(); 

Quant à insérer la quantité et l'id de chaque produit il te faut gérer un panier virtuel(comme on te l'a déjà dit plus haut). Un panier se base sur les sessions et il y a pléthore de tutos qui t'expliquent le principe.

Enfin pour éviter qu'une commande se retrouve accidentellement dans la BD sans les détails de la commande tu peux embarquer tes 2 requêtes d'insertion dans une transaction mysql.transaction