Search code examples
phpwordpresssortingwoocommerceorders

Sorting order items via a hooked function in WooCommerce


In WooCommerce, I have a product attribute pa_location for "location" with which I sort my order items. When order items have the same location, I'd like to sort them by SKU. So, sort first by location and then by SKU.

I looked to "PHP usort sorting multiple fields" but I am unable to figure out how it applies and would work for my function.

I have this custom function that works to sort by pa_location, but cannot get it to also sort by _sku.

I tried implementing some of the examples in the referenced post about sorting.

add_filter( 'woocommerce_order_get_items', function( $items, $order ) {

    uasort( $items,
        function( $a, $b ) {
            return strnatcmp( $a['pa_location'], $b['pa_location'] );
        }
    );

    return $items;
}, 10, 2 );

I hope to sort by location then by SKU using this function. Right now it is only sorting by location.


Solution

  • Try the following based on "PHP usort sorting multiple fields" answers thread:

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

    TESTING:

    $items = array (
        0 => array ( 'pa_location' => 'Marseille',
            '_sku' => '27458C' ),
        1 => array ( 'pa_location' => 'Nice',
            '_sku' => '32458A' ),
        2 => array ('pa_location' => 'Cannes',
            '_sku' => '35C7L5' ),
        3 => array ('pa_location' => 'Marseille',
            '_sku' => '387B85'),
        4 => array ( 'pa_location' => 'Cannes',
            '_sku' => '25A587' )
    );
    
    uasort( $items, function( $a, $b ) {
        if( $a['pa_location'] == $b['pa_location'] ) {
            return strcmp( $a['_sku'], $b['_sku'] );
        }
        return strnatcmp( $a['pa_location'], $b['pa_location'] );
    } );
    // Raw output
    echo '<pre>'; print_r( $items ); echo '<pre>';
    

    We get this output:

    Array
    (
        [2] => Array
            (
                [pa_location] => Cannes
                [_sku] => 25A587
            )
        [4] => Array
            (
                [pa_location] => Cannes
                [_sku] => 35C7L5
            )
        [0] => Array
            (
                [pa_location] => Marseille
                [_sku] => 27458C
            )
        [3] => Array
            (
                [pa_location] => Marseille
                [_sku] => 387B85
            )
        [1] => Array
            (
                [pa_location] => Nice
                [_sku] => 32458A
            )
    )
    

    Which is what we expect, sorting first pa_location and after _sku.