Creating multiple item packages with Ubercart
Recently I have been working on a project which involves a lot of deep integration with Ubercart. For those not in the know, Ubercart is a shopping cart system that is used by Drupal, the content management system I use for building websites. Ubercart is not your only choice for creating a shopping cart, but it is well supported, easy to install and configure and generally up-to-date with modern features. Except packages.
What are packages?
There are many cases where as a seller you will want to package goods together. For instance, if you are purchasing an item and you must get another product in order to make it work (and thus, make your client happy) you want to make sure they order both products at once. A good example might be a computer that requires a special cable. Without the cable the computer does not work. We have to consider that people often forget to click both items, so we are going to find a way of getting around this so users can get more than one item with a single click, or in this example, simply by viewing a page.
Sometimes companies discount package items as well but I am not covering that here, if this is your intent perhaps consider setting up an "alternate" product with the cheaper rate to get the product into the package we are creating today. I'm sure there are other ways, but let's save that discussion for a later date.
Where will the package live?
In most Drupal installations with Ubercart installed you create "Product" pages for your items. We cannot do this for this example because the "Product" content type assumes one product at a time. To get around this, I have made a new content type with a variety of fields that are necessary to describe the products. By doing this, and using CCK and Views magic, I am able to customize the template for this type so that I can drop some PHP code in there. Though I have not tired it, I suspect you may be able to make these API calls from the PHP-enabled pages in Drupal's editor as well.
Empty the current cart
Ubercart's API has a huge amount of information on different calls we can make for adding, editing, or removing items from the shopping cart but I struggled to find exactly what I wanted on the site. To find the answers I needed I went right into the modules themselves and read the code. I also found a few websites that told of the apprently secret API calls that do what we want. So what are they?
The first call I made to Ubercart is a combination call:
uc_cart_empty(uc_cart_get_id());
What this does is empty the cart so that if people view our page more than once they do not see the items being added more than once. There are different ways of doing this, for example, if you want to program a button on the page to do the actual adding of the items (which is probably ideal in most circumstances), you won't need this command at all. For the page I was creating I want the cart to be filled up when the user views the page so this call prevents users from adding items more than once.
The second part of the call is the vital key to making it work - getting the user's cart ID. In fact, this ID number looks a lot like the user's ID number so you could potentially take a shortcut and use that variable but I wanted to keep things pure, so let's use all Ubercart syntax if we can!
Add the items
Putting items into your cart requires two steps. First, you have to reference the node where each product exists already. So if you haven't put any items into your store yet you need to go do that, adding each component one by one. Having done this, you have a "node ID" for each that you can use to add the items to the cart (when you edit a product you will see the node ID - a four digit number - in the address bar).
First, load the node into a variable on your page:
$product_1 = node_load(1234);
Provided that call is successful, you can now query all sorts of information from the product node within your package page. Cool eh? If you want to see all of the available information within a node you can use the print_r command like so:
print_r($product_1);
Note that this command is not necessary for getting the cart to work but it is useful for debugging!
Now, you came here to add something to your cart right? Ok, let's do it:
uc_cart_add_item("$product_1->nid", 1);
There, you have added the item to the shopping cart. Note that there is a second parameter after the product node id (nid). That is the quantity field. You could specify a variable here or hard code a number as I have in this example. You can use this same code to make sure someone buys five of something, ten of something, or more without them having to actually specify the quantity they need just by changing the second parameter.
The nice thing about this code is that it does not modify the checkout process at all so you can safely do this without disruping existing functionality on the site. Users can still add or remove items on the checkout page but they will be much less inclined to do so if they know they are purchasing something as a package and it just took one click to load the cart up with everything.