17

I'm building a custom function for Woocommerce where I need to get product SKU and if 'variation' product get variation specific SKU.

What I currently have is the following:

// Query order data
$order = new WC_Order($order_id);
$items = $order->get_items();

// Output the loop
foreach ($order->get_items() as $item) {
    // Getting some information
    $product_name = $item['name'];
    $product_id = $item['product_id'];
    $product_qty = $item['qty'];
    $product_variation_id = $item['variation_id'];
    $product = new WC_Product($item['product_id']);
    // SKU
    $SKU = $product->get_sku();

It works good except when it comes to variations, I Have spent much time trying to figure this out and to find a good answer without any succes.

I come to understand that I should use something like this:

$available_variations = $product->get_available_variations();

The crazy thing is that I did have this working but I didn't made a Git commit, thus I'm not able to revert the correct code. All the examples I found pretty much exist of a lot of code, but I'm sure this can be done using a much simpler and better performing method.

Tim Visée
  • 2,988
  • 4
  • 45
  • 55
Mathias Asberg
  • 3,562
  • 6
  • 30
  • 46

4 Answers4

29

Talk about tunnel vision..

 $product_variation_id = $item['variation_id'];
 $product = new WC_Product($item['product_id']);

Solution was switching 'product_id' for my already in place 'variation_id'

$product = new WC_Product($item['variation_id']);

Voila, problem solved !

Working example To get the expected output on $sku i did go for this solution

// Get order data
$order = new WC_Order($order_id);
$items = $order->get_items();

// Loop through ordered items
foreach ($items as $item) {
  $product_name = $item['name'];
  $product_id = $item['product_id'];
  $product_qty = $item['qty'];
  $product_variation_id = $item['variation_id'];

  // Check if product has variation.
  if ($product_variation_id) { 
    $product = new WC_Product($item['variation_id']);
  } else {
    $product = new WC_Product($item['product_id']);
  }

  // Get SKU
  $sku = $product->get_sku();
}
honk31
  • 3,895
  • 3
  • 31
  • 30
Mathias Asberg
  • 3,562
  • 6
  • 30
  • 46
  • 3
    You can replace the **if** portion by `$product = $order->get_product_from_item( $item );` [See the get_product_from_item function in /abstract-wc-order.php](https://plugins.trac.wordpress.org/browser/woocommerce/trunk/includes/abstracts/abstract-wc-order.php#L1904) – jflaflamme Sep 22 '16 at 01:22
  • lovely jubbly… @jflaflamme – dj.cowan Dec 15 '16 at 22:40
  • You can even make this shorter by loading the product like this; `$product = $item->get_product()` you don't have to do the if, nor checking the variation_id – Skatox May 31 '17 at 01:13
  • is there any way to do this on the product page? display the selected variations sku when selected and not the master sku – anthonytherockjohnson Jun 05 '17 at 08:04
18

On WooCommerce 3.x this line throws a fatal error:

$product = new WC_Product($item['variation_id']);

Uncaught exception 'Exception' with message 'Invalid Product'.

You can do this:

$sku = get_post_meta( $item['variation_id'], '_sku', true );
Mike
  • 2,686
  • 7
  • 44
  • 61
1

I found this following link massively helpful as adds the SKU to the order item meta so no need for extra calling of functions.

https://majemedia.com/woocommerce-save-item-sku-to-order-item-meta-for-historical-reference/

MikeeeG
  • 331
  • 1
  • 5
  • 21
  • on my phone so can't give you exact answer but I think the issue could be that you not included 'global $products' or if it's global $wc_products, something like that – Mathias Asberg Jul 06 '15 at 18:01
  • Thanks for you reply. I have the global declared earlier in the code. I have used a different method for retrieving the sku. [link](https://majemedia.com/woocommerce-save-item-sku-to-order-item-meta-for-historical-reference/) I will add it to my "answer". Thanks again. – MikeeeG Jul 07 '15 at 12:07
  • 'woocommerce_add_order_item_meta' is now deprecated function… [link](https://docs.woocommerce.com/wc-apidocs/function-woocommerce_add_order_item_meta.html) – dj.cowan Dec 15 '16 at 06:48
0

Tested with Woocommerce 3.8.1


// Define HERE the accepted statuses of that orders 
$order_statuses = array('wc-completed');

// Define HERE the customer ID
$customer_user_id = get_current_user_id(); // current user ID here for example

// Getting current customer orders
$customer_orders = wc_get_orders( array(
    'meta_key' => '_customer_user',
    'meta_value' => $customer_user_id,
    'post_status' => $order_statuses,
    'numberposts' => -1
) );   

// Loop through each customer WC_Order objects
foreach($customer_orders as $order ){

    $order = new WC_Order($order->get_id());
    $items = $order->get_items();

    // Loop through each item of the order
    foreach ( $items as $item ) {
        $product_variation_id = $item['variation_id'];

        if ($product_variation_id) { // IF Order Item is Product Variantion then get Variation Data instead
            $product = wc_get_product($item['variation_id']);
        } else {
            $product = wc_get_product($item['product_id']);
        }

        if ($product) { // Product might be deleted and not exist anymore    
            $sku = $product->get_sku();             
            echo "<p>SKU: " . $sku . "</p>";                
        }  
    }    
}
optimiertes
  • 4,002
  • 1
  • 22
  • 15