Drupal 6 Ubercart price modifications with hook_cart_item()

By shane
Wed, 2012-09-26 17:12
comments

Share with Others

If you need to make price increases when specific attributes or options are selected on products, hook_cart_item() may be able to help you out.

My Drupal 6 Ubercart Dilemma

In a recent situation I needed to create an attribute that contained a price. The trick here is that the price increase needed to be added based on the value selected in another corresponding attribute.

In this example I had one Drupal 6 Ubercart select attribute that was essentially serving the role of a quantity option (I had the traditional Ubercart quantity field disabled). The reason this was set up this way was because this product basically came in packages of select quantities. So the Ubercart attribute had dropdown options of lets say 10, 25, 50, 100, etc.

I had another Ubercart attribute that was created as a single checkbox with a price increase of $0.50. The trick here, was this price increase needed to be based on the quantity dropdown of the number of items in the package.

Drupal Ubercart Attribute Example

This might be a little confusing so I will try to explain it in an example.

  • User goes to the product page
  • User selects quantity if 25, the price of this is $50
  • User selects the single checkbox to trigger the $0.50 price increase per item, the price is now $62.50 ($0.50 x 25 items in the package plus the original $50)

The hook_cart_item implementation

In this example I am just using hard-coded attribute values and option values. Keep in mind this should probably be avoided if possible, but because this was such a unique situation that only occurred for these attributes, I used the hard-coded values for simplicity. This could easily be abstracted into a separate module with an administration interface.

/**
 * Implements hook_cart_item().
 */
function MYMODULE_cart_item($op, &$item) {
  switch ($op) {
    // We only care about the "load" operation, in which a cart item is 
    // being loaded.
    case 'load':
 
      // Here is where I set the hard-coded values for the attribute 
      // and option ids. These values can be pulled from the 
      // Ubercart attribute database tables or from the URLS in the 
      // Ubercart attribute administration pages.
      $quantity_aid = 13;
      $checkbox_aid = 12;
      $checkbox_oid = 50;
 
      // A variable to keep track of the price increases.
      $price_increase = 0;
 
      // Add price increases for my attribute (aid=12, oid=50).
      if (isset($item->data['attributes'][$checkbox_aid][$checkbox_oid])) {
        // Load the attribute so we can determine the price per item that 
        // should be added.
	$checkbox_attr = uc_attribute_load($checkbox_aid);
 
        // Pull the price value (in this case $0.50) from the attribute.
	$price = $checkbox_attr->options[$checkbox_oid]->price;
 
        // Check if the quantity attribute has a selected option value.
        if (is_numeric($item->data['attributes'][$quantity_aid])) {
          $oid = $item->data['attributes'][$quantity_aid];
 
          // Load the attribute so we can pull out the quantity value of 
          // the dropdown.
          $attribute = uc_attribute_load($quantity_aid);
          $quantity = $attribute->options[$oid]->name;
 
          // Make sure the quantity is in fact a numeric value.
          if (is_numeric($quantity)) {
            $price_increase += $price * $quantity;
 
            // Because Ubercart will automatically add the original 
            // attribute price to the total, we need to then subtract out 
            // the original added price.
            $price_increase -= $price;
          }
        }
      }
 
      // Add the price increase to the cart item.
      $item->price += $price_increase;
      break;
  }
}

In the example above, you will need to replace the attribute ids (aid's) and the option id (oid) based on your attributes. You will also need to replace "MYMODULE" with the name of the module you are placing this code in.

Hope this helps someone in a similar situation. If you have any questions or know of a different way to do this, let me know in the comments.