Panier PHP - Tester si un article est dans le panier ...

Petit nouveau ! | 5 Messages

04 juin 2010, 06:17

Bonjour,

je parcours beaucoup ce forum pour mes besoins de développement, j'aurai besoin aujourd'hui d'un éclaircissement.
Le champ "sujet" ne m'a pas permis de clairement m'exprimer alors voici ma situation :

Je développe un site de vente de vêtements en ligne, avec un panier d'achat virtuel.
Le tout fonctionne très bien, j'arrive à mettre à jour mon panier, je sais indiquer au client qu'un article est déjà dans son panier, ...
Je souhaiterai indiquer à un second visiteur qu'un certain article est déjà dans le panier de quelqu'un au moment précis, et le remontrer disponible si le premier client ne finalise pas son achat, où s'il le retire de son panier.

Tous mes articles sont issus d'une base MySQL, lors de leur affichage, je teste leur présence dans la variable $_SESSION, ça fonctionne très bien.
J'ai pensé à inscrire "l'indisponibilité" d'un article dans la base, mais je n'est toujours pas trouvé de solutions pour rendre l'article à nouveau disponible (nouvelle requête SQL) lorsque le premier client ferme son navigateur.
Je me demande donc si de la même façon que je teste si le client a déjà l'article dans son panier, je pourrai tester la présence de l'article dans tous les autres paniers (toutes les autres sessions en cours) ?

Merci pour vos idées.

Je suis disponible si vous avez besoin de plus d'informations.

Cédric

ViPHP
ViPHP | 1136 Messages

04 juin 2010, 08:00

Salut ,

Voilà mon point de vue:

Regarder si l'article 'qui n'est plus dispo' se trouve dans les paniers des autres clients , revient à faire ses courses dans le caddies des autres ..

Pour moi , tu devrais faire une info disant déjà si réellement il en reste en stock .. 1 - 2 - 10 peu importe ( afficher la quantité peur accélérer la commande du client )
Le client l'ajoute au panier ( aucune décrémentation ne se fait à ce moment là ) ,
Vient le moment de valider la commande , là tu vérifies de nouveau les dispos , et tu décrémentes .

Ou alors, tu décrémentes bien lorsque le client met l'article dans son panier , mais tu prévois une déconnexion du client automatique qui a pour effet de "remettre en rayon" les articles qui finalement n'ont pas passé la caisse .
Ce qui aura le même effet donc si le client ferme son navigateur . ( par contre dans ce cas le panier devra être géré en base ! )

Good luck ,

Ch.

Petit nouveau ! | 5 Messages

08 juin 2010, 03:35

Merci pour ta réponse !

Le problème c'est que je n'ai pas de stock, ce sont des articles uniques.
Donc si quelqu'un l'a dans son panier, il faut que je dise à tous les autres "nouveaux visiteurs" (depuis la mise en panier), que l'article n'est plus dispo.

Je souhaite vraiment que cette information s'affiche au plus tôt, et que l'article redevienne disponible dès que l'article n'est pus dans aucun panier, et que la commande n'a pas été effectuée.
Quand je dis au plus tôt, ça peut être 1 ou 2 minutes après, pas à la seconde près.

Merci beaucoup.

Cédric

Mammouth du PHP | 661 Messages

08 juin 2010, 23:50

ben il te suffit de charger ton catalogue de manière récurrente (toutes les x secondes via l'ajax) et à chaque ajout au panier, tu fais une requête ajax visant à inscrire la resa dans une table => ce qui influera sur le catalogue ... ainsi, l'info est connue dans les 20 secondes, même si l'internaute ne recharge pas la page !...

Petit nouveau ! | 5 Messages

11 juin 2010, 03:50

Bonjour et merci pour votre temps,
J'avais bien pensé renseigner une table lors de l'ajout au panier, mais comment modifier la disponibilité dans la table si la personne ferme son navigateur ?
Le catalogue va continuer à se mettre à jour toutes les x secondes mais si l'information en base est restée "article indisponible", plus rien ne pourra le changer !

Je reste toujours bloquer au même niveau : le retour à l'état "disponible".
Puis-je exécuter une requête SQL à la destruction automatique d'une session PHP (x minutes après la fermeture du navigateur) ?

Merci beaucoup^.

Cédric

Albi81php
Invité n'ayant pas de compte PHPfrance

11 juin 2010, 15:54

Bonjour,
A mon avis tu devrais gérer en ajax lors de la fermeture de la fenetre.
Evenement onUnload a utilisé sur toutes tes pages courantes.
Si sa répond à ta question c'est cool, bonne programmation.
Salutation.

Mammouth du PHP | 672 Messages

11 juin 2010, 16:42

Pour rester "simple", je dirais :
Quand un utilisateur se "connecte", on rajoute/met à jour la table Caddies (id_client, id_caddie, date_derniere_visite)
Quand on mets un objet dans le caddie, on rajoute une ligne à la table Objets_Caddies (id_caddie, id_objet)
Quand on le retire, on supprime la ligne.
Quand on consulte le stock d'un objet, on fait une double sélection (sur Objets pour récupérer le stock et sur Caddies), la différence donne le stock. Si le stock est nul et qu'il est dans un/des caddie(s) tu peux le signaler...

Le cas délicat : si quelqu'un quitte.
A chaque fois qu'un utilisateur ouvre une page, on met à jour le champ Caddies.date_derniere_visite, et on supprime les caddies "inactifs" depuis x temps (et les lignes correspondantes dans Objets_Caddies).

J'espère que c'est clair...

Petit nouveau ! | 5 Messages

24 juin 2010, 11:10

Bonjour,

Merci beaucoup pour vos idées !
Je m'excuse pour le délai de réponse, j'ai le cerveau qui fume sur 4 projets de ce type en même temps, c'est vraiment dur !

macdawel, j'ai essayé de mettre en place ta solution, je vois bien que je pars sur la bonne route mais je me retrouve face à un problème différent : J'ai des infos différentes dans ma base et dans mes variables de session, lorsque je supprime mon panier de la base, il reste en session tant que la session n'est pas détruite, et encore une fois, on ne choisi pas vraiment quand elle se détruit (je me suis battu avec le "garbage collection").
Du coup, je suis en train de retranscrire tout mon panier pour utiliser uniquement un stockage en base de données, en laissant tomber les sessions ( je m'en sers juste pour créer un numéro de panier en base à partir de session_id() ).

Mais la bien sur je tombe sur autre chose...ce n'est pas complètement le même sujet alors dites moi si je créer un nouveau post.
Je vous met tout mon code au cas où, mais au moins il y sera.

Le fichier dbinfos.conf est de la forme suivante :
[database]
host = mysql5-13.perso
dbname = nomdelabase
username = monuser
password = monpass

J'ai ma page index.php :

Code : Tout sélectionner

<?php     session_start();          $oldURL = $_SERVER['REQUEST_URI']; // Exemple : /index.php     if($oldURL == '/index.php') {          header("Status: 301 Moved Permanently");          header("Location:/");      }                include('dbinfos/connexionDB.php');     include('panier/fonctions-panier.php'); ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> BLABLABLA </head> ----------------------- ICI LE DIV HEADER ----------------------- <?php //========================================= // includes du fichier fonctions //========================================= require 'fonctions.php';     // Ces fonctions servent uniquement à afficher les numéros de pages et les liens "page précédente" et "page suivante" en fonction du nombre d'article. //========================================= /* get the credentials */ $host = conf('database', 'host'); $db = conf('database', 'dbname'); $user = conf('database', 'username'); $pass = conf('database', 'password'); // ICI echo $host = mysql5-13.perso      $link = mysql_connect ($host,$user,$pass) or die ('Erreur : '.mysql_error() ); mysql_select_db($db) or die ('Erreur :'.mysql_error()); //=========================================     // requête SQL qui compte le nombre total  // d'enregistrements dans la table. //========================================= $select = 'SELECT count(id) FROM articles'; mysql_query("SET NAMES 'utf8'"); $result = mysql_query($select,$link)  or die ('Erreur : '.mysql_error() ); $row = mysql_fetch_row($result); $total = $row[0]; //========================================= // requête SQL qui ne prend que le nombre  // d'enregistrement necessaire à l'affichage. //========================================= $accueil = "'" . "oui" . "'";  $select = 'select id, ref, section, taille, prix, accueil, photo FROM articles WHERE accueil =' . $accueil. ' ORDER BY taille ASC'; mysql_query("SET NAMES 'utf8'"); $result = mysql_query($select,$link)  or die ('Erreur : '.mysql_error() ); ?>          <div id="contenu">        <?php //========================================= // AFFICHAGE DES ARTICLES //=========================================  $col = 0; if($total) {     // lecture et affichage des résultats sur 4 colonnes     $imgAchatID = 0;     while($row = mysql_fetch_array($result)) {         $delai = ($nowTimestamp - $articleTimestamp) / 60;         if ($col <4) {             $col = $col + 1;         }         else {             $col = 0;             $col = $col + 1;         }         $class = "";         if (creationPanier() && !isVerrouille()) {             $produitDansPanier = false; // Forcé à false pour le moment mais un test sera fait ici             $select_article_dispo = 'SELECT id_articles_dans_caddies FROM articles_dans_caddies WHERE ref_article = ' . $row['ref'];             $result_select_article_dispo = mysql_query($select_article_dispo,$link)  or die ('Erreur : '.mysql_error() );             $row_article_dispo = mysql_num_rows($result_select_article_dispo);                          // Si l'article n'est dans aucun panier             if ($row_article_dispo == 0) {                     $class = "ajouterAuPanier";             }             // Sinon, si l'article est déjà dans le panier de quelqu'un             else {                         // Si l'article est dans le panier du client actuel - ARTICLE DANS VOTRE PANIER                 if ($produitDansPanier !== false) {                     $class = "articleDansPanier";                 }                 // Sinon - AJOUTER AU PANIER                 else {                     $class = "articleIndisponible";                 }             }         }         $query_string = 'ref=' . urlencode($row['ref']) . '&section=' . urlencode($row['section']);         $fichier_description_rapide = 'articles/' . $row['section'] . '/' . $row['ref'] . '/description_rapide.txt';         $description_rapide = (file_get_contents($fichier_description_rapide));                  echo '<div class="col' . $col . 'new">                 <div class="himgp">                     <a href="include/simpleviewer/simple.php?' . htmlentities($query_string) . '" onclick="return hs.htmlExpand(this, { objectType: \'iframe\', width: \'900\', height: \'700\' } )" ><img class="imgArticles" src="' . $row['photo'] . '" border="0" alt="' . $description_rapide . '" title="Cliquez pour plus d\'infos" /></a>                  </div>                  <span class="ref">Ref : ' . $row['ref'] . '</span><br /><span class="vendu">' . $row['prix'] . ' &euro;</span>                  <h2 class="titre-sac">' . $description_rapide . '<br />Taille : ' . $row['taille'] . '</h2>                    <div id="achat' . $imgAchatID . '" onclick="majPanier(\'panier/panier.php?action=ajout&l=' . urlencode($row['description']) . '&r=' . urlencode($row['ref']) . '&p=' . urlencode($row['prix']) . '&t=' . urlencode($row['taille']) . '\'); this.className = \'articleDansPanier\'" class="' . $class . '">                 </div>             </div>';     $imgAchatID++;     } } else {     echo 'Pas d\'enregistrements dans cette table...'; } mysql_free_result($result); ?> ----------------------- ICI FERMETURE DU DIV 'CONTENU' LE DIV HEADER ----------------------- </body> </html>
Ma page connexionDB.php :

Code : Tout sélectionner

<?php //========================================= // Récupération des infos de connexion depuis le fichier .conf //========================================= $config = parse_ini_file('dbinfos/dbinfos.conf', true);     //========================================= // Récupération des infos de connexion depuis le fichier .conf //========================================= function conf($section, $option, $default = NULL) {     /**      * We need to bring $config in using global, but this is the only time we'll have to do      * it, meaning if we change $config later, we only have one place to change it in      */     global $config;     /**      * We return the option if [section][option] are set, otherwise we return $default.      * If you like compact, you can crunch this function down into a few (hard to read)      * statements.      */     if (!isset($config[$section]))         return $default;     if (!isset($config[$section][$option]))         return $default;     return $config[$section][$option]; } ?>  
Et enfin ma page fonctions-panier.php :

Code : Tout sélectionner

//========================================= // CREATION DU PANIER - fonctions-panier.php //=========================================  function creationPanier(){      /* get the credentials */     $host = conf('database', 'host');     $db = conf('database', 'dbname');     $user = conf('database', 'username');     $pass = conf('database', 'password'); // ICI echo $host = mysql5-13.perso //=========================================     // Suppression des vieilles sessions // Création du panier ou MAJ de la date de dernière visite // Test des articles disponibles //========================================= // On récupère les infos sur le client $id_client = "'" . session_id() . "'"; $caddie_client =  "'cad" . session_id() . "'"; $date_now = "'" . date("Y-m-d H:i:s") . "'"; // Connexion à la base $link = mysql_connect ($host,$user,$pass) or die ('Erreur : '.mysql_error() ); mysql_select_db($db) or die ('Erreur :'.mysql_error()); mysql_query("SET NAMES utf8"); // On supprime les vieilles sessions ( > 60min ) $delete_old_sessions = 'DELETE FROM caddies WHERE (TIMESTAMPDIFF(MINUTE, date_derniere_visite, ' . $date_now . ') >= 60 )'; $result_delete_old_sessions = mysql_query($delete_old_sessions,$link)  or die ('Erreur : '.mysql_error() ); // On teste l'existence du panier en cours dans la table $select_id_client = 'SELECT id_caddie FROM caddies WHERE caddie_session =' . $id_client; $result_id_client = mysql_query($select_id_client,$link)  or die ('Erreur : '.mysql_error() ); $row_id_client = mysql_num_rows($result_id_client); // Si le résultat est vide (PANIER INEXISTENT) if ($row_id_client == 0) {     // On insère le panier dans la table     $insert_caddie = 'INSERT INTO caddies (caddie_session, date_derniere_visite) VALUES (' . $id_client . ', ' . $date_now . ')';     $result_insert_caddie = mysql_query($insert_caddie,$link)  or die ('Erreur : '.mysql_error() ); } // Si le panier existe déjà else {     // On met à jour la date de dernière visite     $update_caddie = 'UPDATE caddies SET date_derniere_visite = ' . $date_now . ' WHERE caddie_session = ' . $id_client;     $result_update_caddie = mysql_query($update_caddie,$link)  or die ('Erreur : '.mysql_error() ); } return true; } function ajouterArticle($libelleProduit,$refProduit,$tailleProduit,$prixProduit){          /* get the credentials */     $host = conf('database', 'host');     $db = conf('database', 'dbname');     $user = conf('database', 'username');     $pass = conf('database', 'password');     // ICI echo $host = vide ou "localhost" = valeur par défaut si rien n'est trouvé          $link = mysql_connect ($host,$user,$pass) or die ('Erreur : '.mysql_error() );     mysql_select_db($db) or die ('Erreur :'.mysql_error());          $id_client = "'" . session_id() . "'";     $insert_article_caddie = 'INSERT INTO articles_dans_caddies (id_caddie, caddie_session, ref_article) SELECT caddies.id_caddie, ' . $id_client . ', ' . $refProduit . ' FROM caddies WHERE caddie_session = ' . $id_client;     echo $insert_article_caddie;     mysql_query("SET NAMES 'utf8'");     $result_insert_article_caddie = mysql_query($insert_article_caddie,$link)  or die ('Erreur : '.mysql_error() );     } /**  * Permet de savoir si le panier est verrouillé  * @return booleen  */ // Cette fonction va être transformé aussi, mais pour l'instant elle retourne false, donc mes articles en page d'accueil sont affichés function isVerrouille(){    if (isset($_SESSION['panier']) && $_SESSION['panier']['verrou'])    return true;    else    return false; }  
Lors de la phase d'affichages des articles (page index.php), tout marche bien, mes articles sont la.
Si je fais un echo de $host (issue de la fonction conf(), juste en dessous de require 'fonctions.php'; ), il m'affiche bien : mysql5-13.perso (Je suis chez OVH)
- Ma suppression des vieilles sessions fonctionne.
- La création d'un nouveau panier ou la mise à jour d'un existant fonctionne.

Si je fais un echo de $host dans la fonction "creationPanier", il m'affiche bien : mysql5-13.perso

Par contre lorsque je clique sur mon lien "Ajouter au panier" sur un article, la fonction "ajouterArticle" est bien lancée, mais de suite elle me renvoi un message d'erreur : Fatal error: Call to undefined function: conf() in /homez.349/raymond/www/panier/fonctions-panier.php on line 92.
Et si je fais un echo de $host, cette fois-ci à l'intérieur de la fonction "ajouterArticle", $host vaut rien ou "localhost" si c'est la valeur par défaut.

Je pense avoir un problème d'include ou bien de portée de variable....mais je n'arrive plus à m'en sortir.
Est ce que je peux déclarer la fonction conf() dans un include("connexionDB.php"), et l'appeler dans un autre include("fonctions-panier.php") ?
A priori oui puisque que ma fonction "creationPanier" fonctionne.
J'ai essayé de bouger le code dans toutes les positions possibles, je n'y vois plus clair !

Si vous voulez voir de vous même, voici l'url de mon site:
http://www.raymond4.com

J'ai rendu la div où se fait la requete Ajax visible donc lorsque vous cliquez sur "ajouter au panier", sur n'importe quel article, vous avez le message d'erreur tout en haut de l'écran, en noir sur fond très sombre.

Merci beaucoup pour votre aide, si je passe cette étape, le reste devrait couler tout seul.

Cédric

Petit nouveau ! | 5 Messages

26 juin 2010, 11:22

Bonjour à tous !

J'ai finalement trouvé la solution, bien évidemment c'était très bête !

Lorsque je souhaite ajouter un article au panier, je lance une requete Ajax, qui exécute le fichier panier.php
Ce fichier n'avait aucune connaissance de ma fonction conf(), c'est pour cela que le fichier "fonctions-panier" (appelé par panier.php) ne trouvait pas la fonction.

ça me servira de leçon.

Merci encore pour votre aide, vos idées m'ont remis sur le droit chemin !

Je marque ce sujet RESOLU.

Bonne continuation et à très bientôt su ce forum.

Cédric