Woocommerce – Change order of products in Confirmed Order

Using a clean wordpress install, woocommerce and storefront theme, I came up with this code.

It sorts regular products and variable products only. Only sorts in admin panel. Sorts by weight from hgih to low (you can see the commented section, you can uncomment the relevant option to you).

The code goes into functions.php

add_filter('woocommerce_order_get_items', 'bt_sort_woo_order_by_weight', 10, 3);
function bt_sort_woo_order_by_weight ($items, $_this, $types) {
    if (!is_admin()) return $items;
    if (isset($types[0]) && $types[0] !== 'line_item') return $items;

    $items_sorted_by_weight = [];

    foreach ($items as $item_id => $item) {
        // get variation or product id, starting with variation
        $id = !empty($item->get_variation_id()) ? $item->get_variation_id() : $item->get_product_id();

        // get product
        $product = wc_get_product($id);

        // in case the product/variation no longer exist OR product is not variable or simple
        if (empty($product) || !in_array($product->get_type(), ['variation', 'simple'])) {
            $items_sorted_by_weight[] = [
                'weight' => 0,
                'item'   => $item
            ];

            continue;
        }

        $items_sorted_by_weight[] = [
            'weight' => floatval($product->get_weight()),
            'item'   => $item
        ];
    }

    // sort by weight
    usort($items_sorted_by_weight, function($a, $b) {
        //return $a['weight'] <=> $b['weight']; // low to high
        return $b['weight'] <=> $a['weight']; // high to low
    });

    // set each sorted element to contain only the item, nothing else
    foreach ($items_sorted_by_weight as &$item) {
        $item = $item['item'];
    }

    // in case nothing worked set the sorted variable to contain default items
    if (empty($items_sorted_by_weight)) $items_sorted_by_weight = $items;

    return $items_sorted_by_weight;
}