Custom array order in PHP
Recently I found myself in the need to create a list of elements in a very specific order
while working with an array in PHP, fortunately it turns out that the way to achieve
it is very simple, thanks to PHP offering us the usort
function.
Next, I will mention how to achieve a custom order of arrays in PHP.
The code
Taking the following example, I will explain what it consists of:
1<?php2/**3 * Array to order.4 * Let's assume we receive this array from an API where we have no control.5 */6$my_array = [7 'DO',8 'FA',9 'LA',10 'MI',11 'RE',12 'SI',13 'SOL',14];1516/**17 * Order we want, where we have control.18 */19 $custom_order = [20 'DO',21 'RE',22 'MI',23 'FA',24 'SOL',25 'LA',26 'SI',27 ];2829/**30 * We order the array.31 */32usort(33 $my_array,34 function( $a, $b ) use ( $custom_order ) {35 $a_order = array_search( $a, $custom_order );36 $b_order = array_search( $b, $custom_order );3738 if ( false === $a_order ) {39 $a_order = 999;40 }4142 if ( false === $b_order ) {43 $b_order = 999;44 }4546 return $a_order - $b_order;47 }48);4950var_export( $my_array );51
What is happening?
What the function does is not very complex, let's say, it is a loop that iterates over each element in the array, and compares them with each other, finally assigning them a temporary value. The magic happens here when using array_search, which returns the index of the element within the array. The lower the assigned value, the higher priority is given in the order.
1/**2 * Array with emphasized indices:3 */4$custom_order = [5 [0] => 'DO',6 [1] => 'RE',7 [2] => 'MI',8 [3] => 'FA',9 [4] => 'SOL',10 [5] => 'LA',11 [6] => 'SI',12];13
For example, when our algorithm compares DO
vs MI
, it is comparing [0]
vs [2]
,
which are the indices of those elements in the array:
1if ( false === $a_order ) {2 $a_order = 999;3}45if ( false === $b_order ) {6 $b_order = 999;7}8
If it does not find the values within the array (false === $a_order)
, it automatically assigns
a value of 999, which would place them at the end of priorities.
1return $a_order - $b_order;2
Finally, it returns the result of 0 - 2
, or -2
, which would place DO
above MI
, at the moment when MI
vs DO
is compared, the operation would be 2 - 0
,
with a result of 2
which would keep MI
below DO
in priority.
In this way, when the comparisons are finished, we will have our custom order of arrays in PHP ready.
UPDATE 09-27-23
If I already have the order I want defined, why do I need to sort another array?
After my original publication, I realized that it doesn't make much sense to use an example of a single-level array, since immediately after the same array is being placed but sorted, so what's the point of this?.
The real utility comes when we have to sort multidimensional arrays, in this way, based on the value of the array, we can define in what place we want to show it, for example:
1/**2 * Array of teams received from an API3 */4$teams = [5 [6 'id' => 9384,7 'league' => 'NBA',8 'type' => 'basketball',9 ],10 [11 'id' => 89732,12 'league' => 'MLB',13 'type' => 'baseball',14 ],15 [16 'id' => 52,17 'league' => 'MLS',18 'type' => 'football',19 ],20];2122/**23 * Order by preference24 */25$custom_order = [26 'football',27 'basketball',28 'baseball',29];3031/**32 * We order the array.33 */34usort( $teams, ... ); // Same as we used before.3536var_export( $teams );3738/**39[40 [41 'id' => 52,42 'league' => 'MLS',43 'type' => 'football',44 ],45 [46 'id' => 9384,47 'league' => 'NBA',48 'type' => 'basketball',49 ],50 [51 'id' => 89732,52 'league' => 'MLB',53 'type' => 'baseball',54 ],55];56*/57