I have a custom node template based on a custom content type and I want to display products with their "Add to Cart" buttons from this custom node template.

In the content type (actually a field collection), I added the Product reference. In the template (node--{content type}.tpl.php) I do this type of thing:

$wrapper = entity_metadata_wrapper('node', $node);
// Since it's a field collection, I loop these:
foreach ($wrapper->field_content_group as $group) {

  //Now each "$group" has the fields I want to display

  //I permit N products (not just 1), so I can get product information, 
  //like price for example, like this:

  if($group->field_featured_product) {
    $product_references = $group->field_featured_product->value();
    foreach($product_references as $product_reference) {
      $product = commerce_product_load(intval($product_reference->product_id));
      $price = entity_metadata_wrapper('commerce_product', 
      print $price_display = commerce_currency_format($price['amount'], 
                                                    $price['currency_code'], $product);


I don't need to alter the display, I'm happy with that. I'd like to just call something that prints the product, price, etc., along with the "Add to Cart" button. I'm thinking I call commerce_product_load and then some method(s) that gives me the completed form. Is there such a thing that I can call?

NOTE: Yes, I know about separation of concerns and that code is best placed outside of the template file.

  • I've got to ask - if you know it's good practice to separate logic and display, why would you ignore it? This logic should be moved out of the template file and into a preprocess function for all sorts of reasons, not just best practice. Caching for one.
    – Clive
    Oct 22, 2013 at 13:43
  • Work in Process Oct 22, 2013 at 18:04

2 Answers 2


Since views seem to be the easiest way to display product offerings, the way I solved this was to create views for the products. The views are configured as blocks. Then I use:

$block = module_invoke('views', 'block_view', $block_name);
print render($block['content']);

to display the block.

I used content type fields to specify the block names I want to display within certain areas so it isn't hard-coded. It isn't terribly elegant, but sometimes programming is that way since there isn't an infinite amount of time to solve problems!


There is an alternate way of doing this, as shown by duckzland on drupal.org:

Note: You may need to alter the product retrieval code slightly to match the way your node is set up. Using var_dump($content) should help you determine the structure.

Load your product through the node template, without calling commerce_product_load():

$view['product'] = NULL;
// retrieve raw product from field containing your product's info
if(isset($content['product:field_featured_product']) { 
    $view['product'] = $content['product:field_featured_product'];
// do stuff to output the product here
// add to the cart here
// build the line items for shopping cart
$order_id = 0; // optional
$line_item = commerce_line_item_new($view['product']->type, $order_id);
$line_item->data['context']['product_ids'] = array($view['product']->product_id);
$line_item->quantity = 1;
// need to create config for quantity
$qty = 1;
$form_id = commerce_cart_add_to_cart_form_id(array($view['product']->product_id), $qty);
$addtocart_form = drupal_get_form($form_id, $line_item);
// we alter the submit form to use our special theme function
// need to move this to configuration
$addtocart_form['submit']['#theme'][] = 'vtcommerce_button_small';
$variables['cart'] = render($addtocart_form);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.