Jump to content
  • Checkout
  • Login
  • Get in touch


The e-commerce.

Same Products Shown Separately in Cart


Recommended Posts

I have seen this question a couple of times on the forum but have never seen an answer. I have a need to be able to add the same product to the shopping cart twice or more and have it show up as two or more separate items and not simply incrementing the quantity. This is so that variable information can be collected at checkout on a per item basis for certain products.


It looks to be somewhere between application_top and classes/shopping_cart. If I am reading it right, application_top checks to see if there is already a product in the cart with the same id and attributes and if so increments the quantity as part of calling $cart->add_cart(). It looks as though add_cart in classes/shopping_cart is doing the same thing? If you bypass if (($this->in_cart($products_id)) it still increments the quantity! and does not add the new product as a separate new product. I have tried all sorts of permutations of mods to application_top and classes/shopping_cart to no avail - I either get the quantity incremented or the quantity stays at 1 even though you add further products!


Anyone ANY ideas how to get round this? Would appreciate some help or suggestions.



Link to comment
Share on other sites

Anyone ANY ideas how to get round this?

Make the products_id's different? With attributes things like {3}58{90}2345 are added. Perhaps you can add those variables in there some way?

Link to comment
Share on other sites

Make the products_id's different? With attributes things like {3}58{90}2345 are added. Perhaps you can add those variables in there some way?


Thanks for the suggestion. If the product_id is changed then all of the subsequent processes and reporting would not work so I am not sure that is a viable option. The target is to keep the product_id the same so that it always shows up where it should in the checkout and order processes and reports. I had considered adding something unique to each product as it is added to the cart but was not sure if this would mess things up in some way also. Do you know which routine would need to be chnaged to add a randon attribute - I assume it would be {xx}YY tagged on the end. That looks like a good idea.



Link to comment
Share on other sites

An update on this as I have a working solution I would like to share - one of the previous unanswered posts was to do with personalized greetings cards and I am sure the same solution will work.


Our stores all have PayPal-IPN so there was a 'ripple effect' through to the checkout process as we collect personalization information at checkout and hence needed to be able to identify which personalization belonged to which product at checkout and store it in the orders database. That information is then also used for customer confirmation emails and email Purchase Orders to suppliers (we also have Multi-Vendor Shipping and a considerable number of other contributions and home grown additions).


I hope this can help others: (there may be other smarter ways but this worked!)


First part of the fix was to add a random pair of array values to the attributes in the product_id. This turned out to be the most appropriate route to provide a fix. This is done in application_top before any code is processed to add a product to a cart using add_cart. We have a fair amout of new code in there to control who can do what when it comes to adding products but it is easy to locate the case 'add product': and add in at the top under that heading:


$random1 = rand(888888, 999999); 
$random2 = rand(888888, 999999); 
$_POST['id'][$random1] = $random2; 


As not all of our products have personalization we also added code to determine whether the product should have this tagged on the end or not by parsing the attributes first - then adding this if we saw a specific attribute (called Personalization). This means that the cart behaves normally for all products (add two identical products get quantity 2x in the cart) except for those that have personlization where each identical product will show separately in the cart due to the random attribute addded to the array.


Second part was to modify the shopping cart to display only the 'real' attributes for that product and not the random ones. As I set the random number to be high, this was done by the following (can't tell you which line as our code has so many additions and mods that our numbers are not useful). I also wanted to set a flag to tell me whether there was a personalization option chosen for some other routines added to the shopping_cart:


if (isset($products[$i]['attributes']) && is_array($products[$i]['attributes'])) 
 $is_personalization = false;
 while (list($option, $value) = each($products[$i]['attributes'])) 
    if ($products[$i][$option]['products_options_name']=='Personalization')
      $is_personalization = true;
    if ($option <= '888887')
      $products_name .= '<br><small><i> - ' . $products[$i][$option]['products_options_name'] . ' : ' . $products[$i]     [$option]['products_options_values_name'] . '</i></small>';


This checked for an option value in the random number range and if found did not display that attribute. Made for a clean display in the shopping cart.


I did the same in checkout_confirmation as this is where the random attribute would also show to the customer. (Same goes for the customer email confirmation generated following a successful PayPal-IPN transaction). In the case of the checkout_confirmation page the code I found had the attributes displayed by name and not option number as in the shopping cart. So I modified the attribute display code so that it did not show a blank attribute - obviously when the checkout_confirmation routines look up the attribute values the random number query will get nothing from the attributes tables. So the mod was to add an 'if' that did not display the attribute if the option was empty.


if ( (isset($order->products[$i]['attributes'])) && (sizeof($order->products[$i]['attributes']) > 0) ) 
  for ($j=0, $n2=sizeof($order->products[$i]['attributes']); $j<$n2; $j++) {
     if ($order->products[$i]['attributes'][$j]['option'] != '')
       echo '<br><nobr><small> <i> - ' . $order->products[$i]['attributes'][$j]['option'] . ': ' . $order->products[$i]['attributes'][$j]['value'] . '</i></small></nobr>';


Also - otherwise the paypal_ipn routines write a blank attribute to the orders_attributes table.


I did not take the random attribute out of the orders array or shopping cart database table as we wanted it to follow through all the way to order completion. Just did not display it where it was not relevant or could be confusing. It also came in useful to tie personalization data back to the right product on the order.


Third problem was to fix the shopping cart product delete issue - as the product_id is the same for the separately shown indentical products, deleting one from the shopping cart deletes all. This is because the remove product routine in classes/shopping_cart does so by product_id alone and as the separately shown identical products in the cart all have the same product_id they all disappear when you delete one of them.


This required a fix in two places: the first was in application_top to get the case 'update_product': function to pass the whole product id including attributes to the delete routine in classes/shopping_cart so that an individual product could be identified. This was done by adding a new option to the function call (could have just changed it and kept one... but figured that I may need to still delete by simple product_id sometime...):


Was: $cart->remove($_POST['products_id'][$i]);

Now: $cart->remove($_POST['products_id'][$i],$_POST['products_id']);


I then modified the routine in classes/shopping cart to pick up the new function option and to use that to delete the product - both in the product array and the database if the shopping cart was stored (fortunately that uses the full product id complete with attributes and therefore an individual product can be deleted easily with a modified SQL query). As $_POST['products_id'] is an array I also imploded it to get a string of attributes to use in the delete and SQL query.


The function in classes/shopping cart ended up looking like this:


function remove($products_id, $full_products_id) {
 global $customer_id;

 $product_detail = implode('',$full_products_id);


 // remove from database
 if (tep_session_is_registered('customer_id')) {
    tep_db_query("delete from " . TABLE_CUSTOMERS_BASKET . " where customers_id = '" . (int)$customer_id . "' and products_id = '" . $product_detail . "'");
    tep_db_query("delete from " . TABLE_CUSTOMERS_BASKET_ATTRIBUTES . " where customers_id = '" . (int)$customer_id . "' and products_id = '" . $product_detail . "'");

  // assign a temporary unique ID to the order contents to prevent hack attempts during the checkout procedure
  $this->cartID = $this->generate_cart_id();


This took care of most things.


As we ask a customer to input more info at checkout if personalization is ordered (this is done using additional session variables), we used the full product_id string including the attributes and the random attributes as part of the session variable name for the input field that the collected personalization data (could have one or many on an order and hence need to identity each separately). Hence we can tie the variable back to the product it is associated with easily and write the personalization details to the orders tables against the correct product in the paypal_ipn 'pre-process' routines.


Did it this like this:

$personalization_id = "personalize_".$product_id;

And then used it like this at checkout:

echo "<input name='".$personalization_id."' value='".$$personalization_id."'>";


I made one last change in product_info to round this out. Normally our customers can choose multiple products through a dropdown quantity menu. I added code so that if someone choses to personalize a product, the dropdown menu only allows them to pick a quantity of one. This was done with a Javascript routine using display:none/display:block to 'swap' the dropdown quanity menu between one that offers up to a quantity of 15 for one that only offers a quantity of 1. This is triggered by an onChange event in the personalization dropdown menu. This way if a customer chooses to personalise a product, we stop them ordering more than one at a time so that we can track the product through and tie the personalization data collected at checkout to the product ordered. If a customer wnats more than one of a personalized product, they simply add the product more than once into the shopping cart with each showing up separately (with its own random attribute added) and we can track that through and ask for personalization data for each separately.


That pretty much did it. Now we can have selected identical products that have individual personalization show up separately in the shopping cart while all others show up normally and we can also delete them individually. At checkout we use the same random attribute data to track the individual personalization and match it to the product it belongs to.


I hope this info is helpful to anyone with the same problem.


Very many thanks to the forum for all the help it has given me in the past.

Link to comment
Share on other sites

  • 6 months later...

Hi PeterHS


I tried this out, but can't see where it's making a difference. I have OSC installed with the product_type_text option (which allows placement of text/textarea options for products). I quickly discovered a huge flaw with it is that it doesn't make distinct products if you add the same product which causes problems (outlined in this post: http://www.oscommerce.com/forums/index.php?sho...hl=personalized )


For my part, I've modded application_top.php to include the random $POST['id'] generator just inside the add_cart case and changed the remove method further down in the same file


Modded the shopping_cart.php to not show the extranneous ID's.. Didn't do the other mods for checkout_confirmation/email etc... as I'd just like to get this part working...


And I've modded the remove method in the shopping_cart class... I basically get the same effect in that any product with strictly a text option added to the cart with get overwritten when the "same" product with a different text input is written...


Can you offer any suggestions on anything I might have missed? Which tables should I be looking at to see if anything's making a difference - tried the _basket tables with no luck...


Thanks for any suggestions...

** Please do not PM with personal support requests (even if offering "payment"). Thank you.

Link to comment
Share on other sites


This topic is now archived and is closed to further replies.

  • Create New...