Bonsoir,

Pour un site que je développe je dois réaliser un système de panier avec une gestion des commandes (des articles passés et validés dans le panier), ma question serait donc, quel serait le meilleur moyen de stocker et de récupérer mes commandes. Je ne vous cacherais pas que je me suis un tantinet inspiré du tutoriel de grafikart pour réaliser mon système de panier mais je pêche sur la réalisation des commandes.

Ma question est plus d'ordre théorique que technique étant donné qu'actuellement j'essaye de procéder avec un gros tableau $_SESSION'cart'] pour ensuite insérer les articles 1 par 1 dans une table "commandes" à l'aide d'un foreach.

Quelle serait pour vous la meilleure solution/technique ?

Actuellement je procède de cette façon :

addcart.php

$sql = $db->prepare("SELECT *
                         FROM " . PREFIX . "items 
                         WHERE i_id=:id");
    $sql->execute(array(
        'id'    =>  intval($_GET'id']),
    ));
    $item = $sql->fetch();
    if( empty($item) )
    {
        setFlash('This item does\'nt exist', 'danger');
        header('Location:' . WEBROOT . 'categories');
        die();
    }
    if( isset($_SESSION'cart']$item'i_id']]) )
    {
        setFlash('This item is already in your basket', 'danger');
        header('Location:' . WEBROOT . 'item/' . $item'i_slug']);
        die();
    }
    $panier->add($item'i_id'], $item);

cart.php : au moment de l'insertion dans la db

$panier->secure();
        //  On récupère les ids des produits du panier client
        $ids = array_keys($_SESSION'cart']);
        if( empty($ids) )
        {
            $carts = array();
            $s = '';
        }   
        else
        {
            $sql = $db->query("SELECT i.*, img.img_name 
                             FROM " . PREFIX . "items i
                             LEFT JOIN " . PREFIX . "images img
                             ON img.img_id = i.i_image
                             WHERE i.i_id IN (" . implode(',', $ids) . ")");
            $carts = $sql->fetchAll();
            $s = ($sql->rowCount() > 1) ? 's' : '';
        }
        //  On crée une ligne pour chaque article
        foreach($carts as $cart)
        {
            //  On insère la commande dans la base de donnée
            $sql = $db->prepare("INSERT INTO " . PREFIX . " orders SET
                    o_user_id=:user_id,
                    o_item_id=:item_id,
                    o_time=:time,
                    o_number=:number
                    o_statut=:statut,
                    o_total=:total,
                    o_count=:count");
            $array = array(
                'user_id'   =>  $_SESSION'Auth']'u_id'],
                'item_id'   =>  $_SESSION'cart']$cart'i_id']],
                'time' =>   time(),
                'number'    =>  rand(0,999999),
                'statut'    =>  STEP1,
                'total' =>  $panier->total(),
                'count' =>  $panier->count(),
            );
            $sql->execute($array);
        }

et enfin la classe panier, notamment la fonction add :

public function add($id, $item)
    {
        if( $_SESSION'secure'] == FALSE )
        {
            $_SESSION'cart']$id] = array(
                'i_name' => $item'i_name'],
                'i_name_fr' =>  $item'i_name_fr'],
                'i_price' =>    $item'i_price'],
                'i_reference'   =>  $item'i_reference'],
                'i_image' =>    $item'i_image'],
            );
        }
    }

Mais j'obtiens cette erreur :/

Warning: PDOStatement::execute(): SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; 
check the manual that corresponds to your MariaDB server version for the right syntax to use near 'orders SET o_user_id='1', 
o_item_id=NULL, o_time='141393' at line 1

Ce code pourrait éventuellement le faire si jamais $_SESSION'cart']$id] n'était pas nul après un SELECT dans les items... Mais je pense qu'il y a bien plus simple à faire, pour éviter notamment de stocker les informations propres à un article dans les commandes (en cas de modification d'un article par exemple).

Je vous remercie par avance pour vos explications :)

3 réponses


Bonjour

D'abord petite remarque au niveau de ton code, je pense que tu peux te passer des SELECT on enregistrant en Sesssion pas seulement l'ID de l'article mais l’ensemble des données relative à l'article au moment où celui-ci est ajouté au panier.

"Syntax error or access violation: 1064 You have an error in your SQL syntax"

Je verrais bien 2 causes à cette erreur, mais c'est à tester je ne suis pas sur à 100% que ce soit çà :

  • la première : tu soumet une chaine de caractère pour "o_user_id", alors que j'imagine que le champs doit être de type "int";

  • la deuxième : le nom de ta table est "orders", sachant que "order" est un mot réservé en SQL, le problème vient peut être de là mais je suis pas sur... essaie de changer le nom de la table pour lever le doute;

Oui c'est bien la première option le soucis. J'ai tenté de récupérer toutes les informations utiles dans les $_SESSION'cart']$id] = array() mais le soucis c'est pour récupérer seulement l'$id.

Autrement je pourrais simplement me contenter de récupérer l'$id et récupérer le reste au moment de l'insertion, le soucis c'est que ça me ferait faire un select et un insert dans une boucle ce qui pourrait générer jusqu'à mettons 400 requêtes pour un panier... (le principe du site est de faire des petits prix mais en volume donc les paniers joueront facilement entre 50 et 200 articles), ce qui serait bien entendu trop lourd comme système.

On m'a parlé de la méthode serialize mais même après avoir fait un tour sur la doc je ne comprends pas vraiment son fonctionnement et qu'est ce que l'odbc ?

Au final j'ai changé de méthode et j'obtiens toujours une erreur (après moultes essais), l'erreur est la suivante :

Warning: PDOStatement::execute(): SQLSTATE[HY093]: 
Invalid parameter number: number of bound variables does not match number of tokens in

Mon code a évolué de cette façon :

$number = rand(0,999999);
        $sql = $db->prepare("INSERT INTO " . PREFIX . "orders SET
                                 o_user_id=:user,
                                 o_time=:time,
                                 o_number=:number,
                                 o_statut=:statut,
                                 o_total=:total,
                                 o_count=:count");
        $sql->execute(array(
                'user' =>   $_SESSION'Auth']'u_id'],
                'time' =>   time(),
                'number'    =>  $number,
                'statut'    =>  STEP1,
                'total' =>  $panier->total(),
                'count' =>  $panier->count(),
            ));
        $last_id = $db->lastInsertId();
        foreach($basket as $cart)
        {
            $query = $db->prepare("INSERT INTO " . PREFIX . "orders_items SET
                                 'oi_item_id=:item_id,
                                 'oi_order_id=:order_id");
            $query->execute(array(
                'item_id' =>    $cart'i_id'],
                'order_id' =>   $last_id,
            ));
        }

Mais sincèrement je ne vois pas où pourrait se trouver l'erreur :/
J'ai remué les requêtes dans tous les sens, tenté des bindValue pour préparer la requête et rien à faire :/

Si quelqu'un avec un regard extérieur voit l'erreur je suis preneur :)

Merci d'avance :)