1

I am trying to order the products by sku within an order in an email in Woocommerce.

I have not had any luck with the following code.

Some help? Thanks since now!

add_filter( 'woocommerce_order_get_items', function( $items, $order ) {
    uasort( $items,
        function( $a, $b ) {
            return strnatcmp( $a['_sku'], $b['_sku'] );
        }
    );
    return $items;
}, 10, 2 );

Sample sort result:

  • INFSTRAW I
  • NFMUFFIN
  • INFFLORES
  • INFTAFLOR
  • INFTAPINK
  • CTEPINK4
  • CTECAKE4
  • INFCHOCO
  • UCUBTOMA
LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
jpussacq
  • 573
  • 9
  • 29

2 Answers2

3

Updated On July 2020

Here is the way to do it:

add_filter( 'woocommerce_order_get_items', 'filter_order_get_items_by_sku', 10, 3 );
function filter_order_get_items_by_sku( $items, $order, $types ) {
    if( count($items) > 1 ) {
        $item_skus = $sorted_items = array();

        // Loop through order line items
        foreach( $items as $items_id => $item ){
            // Check items type: for versions before Woocommerce 3.3
            if( $item->is_type('line_item') && method_exists( $item, 'get_product' ) ){
                $product = $item->get_product(); // Get the product Object
                if( is_a( $product, 'WC_Product' ) ) {
                    $item_skus[$product->get_sku()] = $items_id;
                }
            }
        }

        // Only for line items when our sku array is not empty
        if( ! empty($item_skus) ) {
            // Sorting in ASC order based on SKUs;
            ksort($item_skus); // or use krsort() for DESC order

            // Loop through sorted $item_skus array
            foreach( $item_skus as $sku => $item_id ){
                // Set items in the correct order
                $sorted_items[$item_id] = $items[$item_id];
            }
            $items = $sorted_items;
        }
    }
    return $items;
}

Code goes in function.php file of your active child theme (or active theme). Tested and works.

This will sort items by sku order ASC on backend and frontend orders and in email notifications


Also sorting items once the order is placed before data is saved to the database, could be a better way to do it.

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
1

In addition to @LoicTheAztec I've added the following check in the code:

if ($product instanceof WC_Product) {
                    $item_skus[$product->get_sku()] = $items_id;
                }

This prevents an error on the front-end customer orders page.

add_filter( 'woocommerce_order_get_items', 'filter_order_get_items_by_sku', 10, 3 );
function filter_order_get_items_by_sku( $items, $order, $types ) {
    if( count($items) > 1 ) {
        $item_skus = $sorted_items = array();

        // Loop through order line items
        foreach( $items as $items_id => $item ){
            // Check items type: for versions before Woocommerce 3.3
            if( $item->is_type('line_item') ){
                $product = $item->get_product(); // Get the product Object
                
                if ($product instanceof WC_Product) {
                    $item_skus[$product->get_sku()] = $items_id;
                }
            }
        }

        // Only for line items when our sku array is not empty
        if( ! empty($item_skus) ) {
            // Sorting in ASC order based on SKUs;
            ksort($item_skus); // or use krsort() for DESC order

            // Loop through sorted $item_skus array
            foreach( $item_skus as $sku => $item_id ){
                // Set items in the correct order
                $sorted_items[$item_id] = $items[$item_id];
            }
            $items = $sorted_items;
        }
    }
    return $items;
}
David
  • 17
  • 4