Here is how you can sort a collection by an ordered array of ids.

The use case here was that I had a number of objects in a Redis cache, which were retrieved in unsorted order. The objects were large, so keeping them cached improved performance. However, the sorting information was not kept on the object, so to get them in the proper order required a table join. Using eloquent, I originally grabbed all the objects directly from the database. However, once the objects were in the cache, I turned it into a two step process. First I got the ids in the correct order, using the original eloquent statement, but I added a pluck statement to only grab the ids. This kept the query fast. Using all(), I returned them as an array.

After getting the collection of objects from the cache, in no particular order, I then sorted them using the array:

$sortedIds = [2536,6374,2562,366,167];  // these are in the desired order
$sortedCollection = $unsortedCollection->sortBy(function($item, $key) use($sortedIds){
     return array_search($item->id,$sortedIds);
});

To understand how this works, let’s say that the id’s in the unsorted collection are in this order:

167,366,2536,6274,2562

First pass:

$item->id = 167

position of this number in $sortedIds array: idx 4, (5th position)

Second pass:

$item->id = 366

position of this number in $sortedIds array: idx 3, (4th position)

As you can see, it is determining where they belong by finding the proper position within the sorted array.

The sortBy function builds up a new array in the correct order, then returns it.

 

Laravel Eloquent sortBy function
Tagged on: