in reply to Need duplicate item entries in shopping cart

You are using a compound key (item_id + color) but storing it by item_id alone. That won't work. Your cart is a hash, which means it won't store duplicates. Your add_item code checks to see if that item_id is there in the cart already before adding it, which will also prevent the same item with two colors from being added twice.

Frankly, this is so obvious that I think you must be asking a different question. Are you asking what a better data structure would be? I'd suggest you give each color a unique item_id, and create a higher-level entity (say, "product") to represent several items that are color variations of the same basic thing. Then your item_id will be unqiue and can be stored in the way you're doing it now.

  • Comment on Re: Need duplicate item entries in shopping cart

Replies are listed 'Best First'.
Re: Re: Need duplicate item entries in shopping cart
by b310 (Scribe) on Feb 19, 2003 at 19:05 UTC
    If anyone can help me with writing my add_item with as an array, I sure could use it.
    Thanks.
Re: Re: Need duplicate item entries in shopping cart
by b310 (Scribe) on Feb 20, 2003 at 00:02 UTC
    Hi Perrin,

    I modified my add_item subroutine to incorporate the arrays. Can you see if I'm on the right track?

    I believe that I'm way off base. Especially when it comes to the quantity field. Quantity is a parameter that is being passed. It's not in the database table so I don't know how to incorporate that into the array.

    sub add_item { my @item_ref; my @cart_ref; my ($dbh, $cart_ref, $item_id, $qty, $color) = @_; # If the item isn't already in the cart, look it up from the datab +ase # and store it in the cart as a new entry with a quantity of zero. if (!exists ($cart_ref->{$item_id})) { my $sth = $dbh->prepare ("SELECT item_id, description, categor +y, price, picture, thumbnail, mime_type, color FROM catalog_pet WHERE item_id = ?"); $sth->execute ($item_id); my $item_ref = $sth->fetchrow_arrayref (); $sth->finish (); return if !defined ($item_ref); # this shouldn't happen... @cart_ref->[0] = {}; # create new entry, indexed by item ID @cart_ref->[1] = $item_ref->{description}; @cart_ref->[3] = $item_ref->{price}; @cart_ref->[8] = 1; } @cart_ref->[8] = $qty; @cart_ref->[7] = $color; push (@cart_ref, @item_ref); }
      Well, first of all you have to change ALL of your code that uses this cart structure -- not just this one sub -- if you want to switch the cart from a hash to an array. I actually think this is probably the wrong approach and you would be better off making unique item ids for every one of your colors. You could also cheat by making a generated key to use in your shopping cart: my $item_key = $item_id . '|' . $color or something like that.

      Just to give you an idea of what you need to do to that code to change it to arrays, here is another take on your add_item sub:

      sub add_item { my ($dbh, $cart_ref, $item_id, $qty, $color) = @_; # If the item isn't already in the cart, look it up from the datab +ase # and store it in the cart as a new entry with a quantity of zero. my $saw_item = 0; foreach my $item (@{$cart_ref}) { if (($item->{'id'} == $item_id) && $item->{'color'} eq $color) +) { $saw_item = 1; break; } } if (!$saw_item) { my $sth = $dbh->prepare ("SELECT item_id, description, categor +y, price, picture, thumbnail, mime_type, color FROM catalog_pet WHERE + item_id = ?"); $sth->execute ($item_id); my $row = $sth->fetchrow_hashref (); return if !defined ($row); # this shouldn't happen... my $item_ref = {}; $item_ref->{description} = $row->{description}; $item_ref->{price} = $row->{price}; $item_ref->{qty} = 1; $item_ref->{color} = $color; } $item_ref->{qty} = $qty; push (@{$cart_ref}, @item_ref); }
      Note that it is no longer possible to look up a single item in the cart by ID with this structure: you have to loop through all the items.
        Hi Perrin,

        I understand what you're trying to tell me. I think my solution will have to be with the database structure. I don't want the script to loop through all the items all the time. I believe a lot of processing time would be required to run the script.

        So, I'm going to investigate the database option. From your earlier reply to the node you mentioned a higher entity.

        Here's an example of the database structures and let me see if I understand what you're trying to suggest.

        Product Table:
        item_id: 7
        description: ball
        category: toys
        price: 5.69
        PRIMARY KEY item_id

        Color Table:
        color_id: 7br
        item_id: 7
        color: blue

        color_id: 7gr
        item_id: 7
        color: green

        color_id: 7or
        item_id: 7
        color: orange

        PRIMARY KEY color_id
        FOREIGN KEY item_id

        I would write a SQL that would join these two tables, along the lines:

        SELECT product.item_id, product.description, product.category, product.price, color.color WHERE product.item_id = color.color_id GROUP BY product.item_id, product.description, product.category, product.price;

        If I'm on the right track thus far, will I have a popup menu with the individual colors for a single item as well as be able to choose that item more than once with a different color?

        Here's my online catalog:

        Item picture, item description, item price,
        a popup menu that will show me the colors: blue, green orange for this item.
        To get a better idea, please visit: http://www.summitwebcrafters.com/cgi-bin/pet_shop1.cgi

        Click on the Toys category and the first item on the page is the item that has colors at the moment.

        With the above database structure, will I be able to achieve the look and feel of that Toys page, with the color popup menu, and the ability to add that same item with two different colors?

        Do you think I'm on the right track?