Add items to the cart with custom forms
The request for more robust Ubercart add to cart forms comes up fairly regularly. People generally have in mind the sort of form that allows customers to specify quantities for a set of products and add them to the cart all at once. The request came up so often that I put a short explanation on how to accomplish this through a custom form into an FAQ post on Ubercart.org.
This article will walk through a very basic example of how you can use the Ubercart function uc_cart_add_item() in a custom form submit handler to add multiple items to the cart at once. This article assumes a basic knowledge of Drupal's Forms API. Code examples are from Drupal 6, but they are mostly applicable to Drupal 5 as well.
The Ubercart Shopping Cart
Before digging into the code to actually add items to the cart, it's a good idea for developers to have a basic idea of how the shopping cart works in Ubercart.
In Ubercart 1.x and 2.x, the shopping cart is represented in the database as a set of rows in the uc_cart_products table all related to the same user through a cart_id. Other fields in the database table include:
- nid - the node ID of the product node
- qty - the number of this product currently in the cart
- changed - the timestamp tracking the last update to the item
- data - an array that modules can use to store information about the product in the cart
When a cart is loaded through the function uc_cart_get_contents(), it is represented as an array of cart item objects. Each cart item will have the above fields as class properties along with others from the corresponding product nodes holding data like price and SKU.
Adding Items to the Cart
When adding items to the cart, you simply have to call uc_cart_add_item() with a fairly limited set of parameters. At its very basic, you can add an item just by passing the nid of the product node. If you created a product as node 2, you can add one of this product to the current user's cart just by using the code:
<?php
// Adds one of product 2 to the current user's cart.
uc_cart_add_item(2);
?>You can easily specify how many of the product to add to the cart using the function's second parameter:
<?php
// Adds three of product 2 to the current user's cart.
uc_cart_add_item(2, 3);
?>In either of these cases, Ubercart will look in the current user's cart for any instances of product 2. If a match is found based on the nid and data array in the database, the qty for that product is simply incremented the appropriate amount. Otherwise, Ubercart will add a new row to the uc_cart_products table representing the product with the appropriate qty.
A full list of parameters for uc_cart_add_item() includes:
- $nid - the nid of the product
- $qty - the quantity of the product to add to the cart
- $data - an array of data related to the product
- $cid - the ID of the cart to add the product to; if left NULL, the current user's cart will be used
- $message - whether or not to display a message to the user indicating that the product as added to the cart
- $check_redirect - whether or not to check for and return the add to cart redirect based on the site's cart settings
Building a Form for Adding Multiple Products
So, knowing the basics of how the Ubercart shopping cart works, it's time to look at how to use this knowledge in a simple form. Let's imagine for a moment that you want to add a form to your site allowing users to add any number of several products from your store to the cart at once. You know the product node IDs, so you throw together a simple form like the following:
<?php
// Build a custom add to cart form.
function multi_add_form() {
$form = array();
// Make the products array in the form a tree.
$form['products'] = array(
'#tree' => TRUE,
);
// Use an array of product nids to build the form.
$nids = array(2, 47);
// Add a quantity field for each product.
foreach ($nids as $nid) {
$node = node_load($nid);
$form['products'][$nid]['qty'] = array(
'#type' => 'textfield',
'#title' => t('Qty. of @title', array('@title' => $node->title)),
'#size' => 16,
'#default_value' => 0,
);
}
// Add an add to cart button.
$form['add_to_cart'] = array(
'#type' => 'submit',
'#value' => t('Add to cart'),
);
return $form;
}
?>Handling User Input in the Submit Handler
Now it's time to do something with user input once this form is submitted. We'll actually want to turn the data into parameters for us with uc_cart_add_item(), so let's have a quick look in a submit handler for this form at the structure of the data. You can use the following submit handler to see what Drupal passes in as form values:
<?php
function multi_add_form_submit($form, &$form_state) {
drupal_set_message('<pre>'. print_r($form_state['values'], TRUE) .'</pre>');
}
?>The output for a submission of the above form for someone ordering 3 beanies and 1 Uberclub membership would include:
Array
(
[products] => Array
(
[2] => Array
(
[qty] => 3
)
[47] => Array
(
[qty] => 1
)
)
)Since we set the products array in the form array to be a tree, the Forms API passes to our submit handler an array of form values with a similar hierarchy to the elements in the form array. This means we can easily poll through the products on the form and call uc_cart_add_item() to add the correct quantity of each item to the cart like so:
<?php
function multi_add_form_submit($form, &$form_state) {
// Loop through the products array.
foreach ($form_state['values']['products'] as $key => $value) {
// The key is the product nid, the value holds the qty.
if ($value['qty'] > 0) {
// Add the item to the cart if the quantity was increased.
uc_cart_add_item($key, $value['qty']);
}
}
// Display a message and redirect to the cart.
drupal_set_message(t('Your cart has been updated.'));
$form_state['redirect'] = 'cart';
}
?>Conclusion
There's certainly more you can do with a form like this. You might change the way the form elements are added to the form array and themed for display, add a validate handler to the form to check for valid quantity values, or use the actual return value of uc_cart_add_item() for the redirect.
However, this simple example should at least help you get started using the Ubercart API to build custom add to cart forms to better serve your customers.



Comments
Somethings about making this
Somethings about making this correct, you should test if you can place this product in cart:
<?php
function multi_add_form_submit($form, &$form_state) {
// Loop through the products array.
foreach ($form_state['values']['products'] as $key => $value) {
// The key is the product nid, the value holds the qty.
if ($value['qty'] > 0) {
// Add the item to the cart if the quantity was increased.
$result = module_invoke_all('add_to_cart', $key, $value['qty'] );
if ( !is_array($result) )
{
uc_cart_add_item($key, $value['qty']);
} else {
// output message $result
}
}
}
// Display a message and redirect to the cart.
drupal_set_message(t('Your cart has been updated.'));
$form_state['redirect'] = 'cart';
}
?>
This is wonderful article
This is wonderful article which explains the flexibility of ubercart. I will keep coming to commerceguys doc section for more updates.
One suggestion as to how the comments in this page are displayed. There is no clear division of the content and the comment, which would lead to a casual reader (like me) to think comments as part of the content, especially when the comment also starts with a bunch of code like here.
Great article! I can't wait
Great article! I can't wait to play around with this!
The screenshot of the finished form is broken - I'd really love to see an image of form.
Thanks!
I have this example working
I have this example working perfectly.
Now I need to be able to display the title, teaser and attributes for each product. How would I go about doing this?
(Thanks for your patience - I am not a programmer!)
Post new comment