Pour gérer un système de ventes j'ai 4 table dans ma base( une image ira plus vite et sera plus compréhensible qu'un long texte)
Donc ma question est-ce que perd en optimisation d'avoir le prix_unit_produit dans la table commande_produit ? Puisque je voudrais aussi rajouter le nom du produit. Pourquoi? Je sais très bien que je peux récupérer les infos de mon produit avec une simple requête. mais c'est pur "simplifier mon affichage en php dans le bon de commande, qui ce fait avec une boucle foreach
<?php $req=$pdo->prepare('SELECT * FROM commande_produit WHERE id_commande=:id_commande GROUP BY id_product');
$req->execute(['id_commande'=>'36']);
$products_commande=$req->fetchall();
var_dump($products_commande);
foreach ($products_commande as $product ):?>
<tr>
<td><?=$product->quantite_produit ?>
<td><?= $product->id_product?></td>
<td style="width: 78px"><?=$product->prix_unit_produit?></td>
<td style="width: 108px"><?=$product->prix_total_produitHT?></td>
</tr>
<?php endforeach?>
Le probleme c'est que si je sépare mes infos il me faudra 'complexifié' mon code php ( Je récupere id_product à la place du nom vue que je l'ai pas ajouté en bdd encore )
Donc voila est-ce que je perd en performance en créant ses doublons? Ou mon système est il assez simple pour que ce ne soit négligeable ?
Merci à vous
Edit:
Dans un point de vu plus sécurité mainteant, j'aurais 2 variables à faire passer à la page qui me genere mon pdf (celle avec le foreach), la quantité totale, et le prix_totalHT. Les récuperer depuis la bdd ets beaucoup mieux d'un point de vu sécurité que de le faire passer via un $_POST ou $_SESSION non?
Ha j'ai oublier le closeCursor() sur la apres la requete, il est important à quel point en fait ? Puisque s'en ça marche 'bien'.
- Edité par QuentinVidal5 10 août 2018 à 10:19:34
Le plus souvent la cause du bug est situé devant l'écran ;)
Non il ne faut pas avoir de notion de prix dans la table commande_produit.
Il y a toutefois une exception, pour une commande passée et payée, si le prix d'un produit devait évoluer, une ancienne commande n'afficherait plus le prix auquel le produit a réellement était payé. Il faut dans ce cas créer une table historique des prix, et faire une jointure sur le prix au moment où la commande a été passée.
Il est évident que tout le reste (comme le prix_total_produitHT) doit être calculé à chaque requête. Il faut bien comprendre que pour avoir une base de donnée solide, il ne faut pas avoir de considération sur la facilité à l'utiliser avec un langage (ici PHP).
Car pour ce qui est de la facilité d'exploitation, il y a d'autres outils pour ça : les vues et les fonctions ! C'est dans une vue que tu peux te permettre de dénormaliser, et avoir un champ prix_total_produitHT. Ton code PHP pourra alors interroger la vue exactement comme si c'était une table. Ca sera transparent pour lui.
Pour les changement de prix, une colonne réduction peux faire l'affaire non ? A ben non si tout les prix chnage la réduction n'aura plus la même valeur.
Donc je fais une table historique des prix avec par exemple ->
id[pk], id_product[fk], date_debut_prix (Date ou le nouveau prix est utilisé), date_fin_prix (date ou le prix à été changé, null si prix toujours valable)
Et dans ma table commande_produit je met une colonne historique_prix_id, qui me permettra de faire une jointure pour avoir le prix du produit lors du passage de la commande
Le plus souvent la cause du bug est situé devant l'écran ;)
La date_fin_prix n'a pas d’intérêt, car cette donnée peut être calculée : il s'agit de la date de début du prix suivant.
Je créerais ce genres de table :
CREATE TABLE PRICE_HISTORY (
id_product INTEGER NOT NULL,
date TIMESTAMP NOT NULL DEFAULT NOW(),
price FLOAT NOT NULL,
PRIMARY KEY(id_product, date),
FOREIGN KEY(id_product) REFERENCES PRODUCT(id),
);
Note : la clef primaire composite ne sert pas qu'à s'assurer que l'on ne puisse pas enregistrer deux prix différents pour le même produit au même moment. Elle sert aussi à créer un index (automatiquement créé, comme pour toute clef primaire ou contrainte UNIQUE) permettant d’accélérer les requêtes de recherche du dernier prix par produit. On aurait très bien pu créer une clef en auto incrément, et une contrainte UNIQUE, mais cela aurait rajouté un index supplémentaire, et donc un coût dans la taille de la base de donnée et dans les temps d'écriture (puisqu'il faut mettre à jours tous les index).
Ainsi, on peut retirer la colonne "price" de la table "product". Et voici la VUE à créer pour retrouver l'affichage que tu as actuellement (cad avec le prix):
CREATE VIEW V_PRODUCT_PRICE AS
SELECT p.*, price
FROM PRODUCT
INNER JOIN (
SELECT TEMP.id_product, price
FROM PRICE_HISTORY
INNER JOIN (
SELECT id_product, MAX(date) as date
FROM PRICE_HISTORY
GROUP BY id_product
) as TEMP
ON TEMP.id_product = PRICE_HISTORY.id_product AND TEMP.date = PRICE_HISTORY.date
) as PRICE
ON PRICE.id_product = p.id
Cette vue va recherche pour tous les produits la dernière date de changement de prix, et récupérer le prix pour chaque couple.
Afficher la liste des produits avec le dernier prix devient très facile :
SELECT *
FROM V_PRODUCT_PRICE -- au lieu de PRODUCT
Ta nouvelle requète pour afficher la commande (avant paiment) doit ressembler à ceci :
SELECT commande_produit.*, price as prix_unit_produit, price * quantite_produit as prix_total_produit_HT
FROM commande_produit
INNER JOIN V_PRODUCT_PRICE
ON V_PRODUCT_PRICE.id = commande_produit.id_product
WHERE id_commande=:id_commande
Après paiement il faudra "fixer" le prix en spécifiant la colonne historique_prix_id comme tu le propose.
Merci beaucoup pour tout ce travail, je vais essayer d'intégrer tout ça correctement
Ma base est pas enorme pour l'instant, mais si elle est pas optimisé pour le départ ça risque d'être vite le bordel apres
Le plus souvent la cause du bug est situé devant l'écran ;)
Optimisation bdd
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.