Had a request by a client to sort / rearrange the individual order items that you see on the WordPress admin side (i.e. on the WooCommerce “Edit order” page ).
For this particular case, each order item has a date string saved in the item meta. They wanted the items to be sorted from earliest date to latest date.

After some searching, I found this super old post by Josh Kohlbach which I modified to work. Here is how I did it.
Step 1: ‘woocommerce_order_get_items’ filter
The first step was getting the correct WooCommerce hook to use. Luckily, there is a filter hook to use: woocommerce_order_get_items
It returns an array of the items in the order.
So, let’s set up the basic snippet:
function custom_order_items_sort($items, $order) { // code goes here.. return $items; } add_filter('woocommerce_order_get_items', 'custom_order_items_sort', 10 ,2);
Step 2: Use PHP function ‘uasort’
We can then use the builtin PHP function uasort
, which allows us to sort an array with our own custom sorting function.
The basic syntax is something like uasort(array, sortingFunction)
.
The array we are using $items
is provided by the filter hook. So, now all we need to do is create a new custom sorting function that I have named my_sorting_function
. You could do it inline also, but I think it’s easier to read this way.
function custom_order_items_sort($items, $order) { uasort($items, my_sorting_function); // sorts array $items with `my_sorting_function` return $items; } function my_sorting_function ($a, $b) { // our new custom sorting/comparison function //sorting code goes here } add_filter('woocommerce_order_get_items', 'custom_order_items_sort', 10 ,2);
Step 3: Building a custom sorting function
uasort
works by comparing two items at a time (i.e. $a
, $b
) from the array (i.e. $items
), and sorts them according to the provided function (i.e. my_sorting_function
).
The custom sorting function must compare the two items, and return an integer (usually -1, 0, 1) to arrange the items in the needed order. Here’s a basic example of how sorting works…
uasort basic example
Our array we want to sort is [2, 7, 3]
. If we want to use uasort
to sort from smallest to largest, the basic sorting function would look something like this:
//just an example function example_sort_function ($a, $b) { if ($a == $b) return 0; // if they are the same, we don't need to rearrange order if ($a < $b) return -1; // if a less than b, move it before b if ($a > $b) return 1; // if a is greater than b, move it after b }
This function would first compare 2 ($a) and 7 ($b). Since 2 < 7, it would return a value of -1, which would move 2 before 7. Since 2 is already before 7, nothing happens to the array.
Then, it would continue to the next pair and compare 7 with 3. Since 7 > 3, it would return a value of 1, and move 7 after 3. uasort
continues to loop through all possible pairs in the array until it is completely sorted. In this example, the final array is [2,3,7]
.
Back to our snippet…
For our snippet, we need to first get the meta data from each order item.
We can do this with get_meta_data()
function, which gives us an array of all meta data for that item.
function custom_order_items_sort($items, $order) { uasort($items, my_sorting_function); // sorts array $items with `my_sorting_function` return $items; } function my_sorting_function ($a, $b) { $a_meta_data = $a->get_meta_data(); // get meta data for a $b_meta_data = $b->get_meta_data(); // get meta data for b } add_filter('woocommerce_order_get_items', 'custom_order_items_sort', 10 ,2);
Then, we need to loop through each item’s meta data to find the specific key we need. In my case, I am looking for “Date” meta key and value. I then had to convert the date string into a date object so I could compare them properly.
function custom_order_items_sort($items, $order) { uasort($items, my_sorting_function); // sorts array $items with `my_sorting_function` return $items; } function my_sorting_function ($a, $b) { $a_meta_data = $a->get_meta_data(); // gets array of meta data for a $b_meta_data = $b->get_meta_data(); // gets array of meta data for b // gets the date object for a foreach($a_meta_data as $key=>$meta_array) { if($meta_array->key == "Date") { // looking for "Date" meta key $a_date = $meta_array->value; // returns date string like "28/05/2022 7:00 am" $a_date = DateTime::createFromFormat('d/m/Y g:i a', $a_date); // convert to date object for comparison } } // gets the date object for b foreach($b_meta_data as $key=>$meta_array) { if($meta_array->key == "Date") { $b_date = $meta_array->value; $b_date = DateTime::createFromFormat('d/m/Y g:i a', $b_date); } } } add_filter('woocommerce_order_get_items', 'custom_order_items_sort', 10 ,2);
Yes, I repeated my code. You could probably make this nicer somehow. Maybe someone out there has a suggestion?
Step 4: Final Snippet
The final step is to compare the dates and return -1, 1, or 0.
function custom_order_items_sort($items, $order) { uasort($items, my_sorting_function); // sorts array $items with `my_sorting_function` return $items; // don't forget to return the sorted items } function my_sorting_function ($a, $b) { $a_meta_data = $a->get_meta_data(); // gets array of meta data for a $b_meta_data = $b->get_meta_data(); // gets array of meta data for b // gets the date object for a foreach($a_meta_data as $key=>$data_array) { if($data_array->key == "Date") { // looking for "Date" meta key $a_date = $data_array->value; // returns date string "28/05/2022 7:00 am" $a_date = DateTime::createFromFormat('d/m/Y g:i a', $a_date); // convert to date object for comparison } } // gets the date object for b foreach($b_meta_data as $key=>$data_array) { if($data_array->key == "Date") { $b_date = $data_array->value; $b_date = DateTime::createFromFormat('d/m/Y g:i a', $b_date); } } // compares the dates if ($a_date == $b_date) return 0; // if dates are same, do nothing return ($a_date < $b_date ) ? -1 : 1 ; // if a_date is earlier than b_date, moves $a before $b, else move after } add_filter('woocommerce_order_get_items', 'custom_order_items_sort', 10 ,2);
That’s it! 🙃
I hope this helps someone out there.