Partage
  • Partager sur Facebook
  • Partager sur Twitter

Optimisation bdd

récup d'info dans un foreach php

    10 août 2018 à 9:54:29

    Bonjour à tous,

    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

    • Partager sur Facebook
    • Partager sur Twitter
    Le plus souvent la cause du bug est situé devant l'écran ;)
      10 août 2018 à 10:34:59

      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.

      • Partager sur Facebook
      • Partager sur Twitter
        10 août 2018 à 13:37:26

        Merci beaucoup pour ta réponse,

        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

        • Partager sur Facebook
        • Partager sur Twitter
        Le plus souvent la cause du bug est situé devant l'écran ;)
          10 août 2018 à 19:23:15

          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.



          -
          Edité par Sebajuste 10 août 2018 à 19:43:00

          • Partager sur Facebook
          • Partager sur Twitter
            13 août 2018 à 8:24:00

            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

            • Partager sur Facebook
            • Partager sur Twitter
            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.
            • Editeur
            • Markdown