Creating Orders with Custom Line Items using the Drupal Commerce API

If you've found yourself needing to create a custom order with the Commerce API, you've likely come across this article "Creating orders with the Drupal Commerce API" or found your answer from the Commerce Examples module. The solution provided works great, but it doesn't tell you how to assign values to custom fields you've created for line items. Here's how you do it.

The Code

function example_create_order_with_product($product_id, $line_item_values = array(), $uid = NULL, $use_cart = TRUE) {
  global $user;
  // Make sure the user id is set.
  if (is_null($uid)) {
    $uid = $user->uid;
  }
 
  // First, see if there is already a cart for this user.
  // Here we will not assume that commerce_cart is enabled.
  if (module_exists('commerce_cart') && $use_cart) {
    $order = commerce_cart_order_load($uid);
  }
 
  if (empty($order)) {
    // Create the new order in checkout status with a custom order type of "donate_now_order_type".    
    $order = commerce_order_new($uid, 'commerce_checkout');
 
    // Save the order so its ID is assigned.
    commerce_order_save($order);
  }
 
  // Load whatever product represents the item the customer will be
  // paying for and create a line item for it.
  $product = commerce_product_load($product_id);
 
  // Create a line item with quantity 1 and this product.
  $line_item = commerce_product_line_item_new($product, 1, $order->order_id, array(), 'donation');  
 
  // Add the custom values to the line_item fields
  foreach ($line_item_values as $field_name => $value) {
    $line_item->{$field_name}[LANGUAGE_NONE][0]['value'] = $value; 
  }
 
  // Save the line item to get its ID.
  commerce_line_item_save($line_item);
 
  // Add the line item to the order using the wrapper.
  $order_wrapper = entity_metadata_wrapper('commerce_order', $order);
  $order_wrapper->commerce_line_items[] = $line_item;
 
  // Save the order again to update its line item reference field.
  commerce_order_save($order);
 
  return $order->order_id;
}

The Logic

The majority of the code from above is pretty much the same as you'll find in the other articles. The difference is that I'm passing a variable called $line_item_values. The variable is structured so that the field name is array key and the field value is the value. You don't have to use an array, if you don't have more than one field you're setting values for. For my scenario this made sense.

From that variable, loop through and set the value for each field after creating the line item and before saving it. Depending on the complexity of the field you're trying to populate, you may need to play around with the value assignment.

But that's it. It's not a real complicated or fancy solution, but I couldn't find the answer anywhere else.