12

My question is simple: How do I get the product id's from a commerce order with Drupal code? I have something like this at the moment:

  $orders = commerce_order_load_multiple(array(), array('status' => 'pending'), TRUE);
  foreach($orders as $order) {
    foreach ($order->commerce_line_items['und'] as $line) {
        $line_id = $line['line_item_id'];
        // ... product id, where are you?
    }

Hopefully somebody is able to answer this question :)

  • Have you tried var_dump($order); inside your 2nd foreach? – saadlulu Feb 28 '12 at 14:33
9

I can't remember the exact structure of the commerce product reference field, but you need to do something like this.

Warning this code style won't work on many orders as the internal cache for the line item entities will use too much memory. This will be a problem if you have thousands of orders.

$orders = commerce_order_load_multiple(array(), array('status' => 'pending'), TRUE);
foreach($orders as $order) {
  foreach ($order->commerce_line_items['und'] as $line) {
    $line_item = commerce_line_item_load($line['line_item_id']);
    $product_id = $line_item->commerce_product['und']...
  }
}
  • Thanks, this works. I got the idea that running a query on the commerce tables was also an option. There a relationship order - product could have been established with the sku field. – user5706 Feb 28 '12 at 14:43
  • Me too. Pity that when I have order ID, I cannot just query product IDS, but I have to load so much objects. – tomas.teicher Nov 22 '13 at 5:33
  • It's not great practice to use 'und' directly. If you're certain your code will only be used on an untranslated site, you can use the LANGUAGE_NONE constant - but it's better practice to use field_get_items() to get the items from the field, and iterate through that instead. So foreach ($order->commerce_line_items['und'] as $line) { ... } becomes $items = field_get_items('commerce_order', $order, 'commerce_line_items'); foreach ($items as $line) { ... }, etc. Or, use entity_metadata_wrapper, which automatically takes languages into account. – KingAndy May 3 at 9:38
22

Using the entity metadata wrapper, you could also do:

foreach (commerce_order_load_multiple(array(), array('status' => 'pending'), TRUE) as $order) {
  $product_ids = array();
  foreach (entity_metadata_wrapper('commerce_order', $order)->commerce_line_items as $delta => $line_item_wrapper) {
    if (in_array($line_item_wrapper->type->value(), commerce_product_line_item_types())) {
      $product_ids[] = $line_item_wrapper->commerce_product->raw();
    }
  }
}

The important part here is checking the type of the line item, so you don't end up including shipping line items or other types of line items in your list of product IDs. Additionally, with the wrapper notice that I used the "raw" value of the commerce_product field on the line item. This is because the "value" would be the fully loaded referenced product, while the "raw" value is simply the product ID.

3

If you don't need to load whole objects (line items, order and commerce products) You could run query like this:

 $args = array(
    ':order_id' => $order_id,

);
$product_ids = db_query("SELECT p.commerce_product_product_id 
   FROM {commerce_line_item} li 
   JOIN {field_data_commerce_product} p ON (p.entity_id = li.line_item_id) 
   WHERE li.order_id = :order_id AND li.type = 'product'", $args)->fetchCol();
return $product_ids;
  • mapping the data to DB can be quite a daunting task.. thanks for this mapping info.. have been searching for this since 2 days – mjs Aug 2 '16 at 7:27
  • In theory other entity types could be using the commerce_product field, so the Join would more appropriately be JOIN {field_data_commerce_product} p ON (p.entity_id = li.line_item_id AND p.entity_type = 'commerce_line_item') – KingAndy May 3 at 9:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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